mirror of https://github.com/digarok/gsplus.git
using code beautifier (uncrustify), possibly most controversial commit ever\?
This commit is contained in:
parent
a509cc0a3c
commit
65f280569c
|
@ -23,3 +23,6 @@ images/
|
|||
|
||||
# Screenshot dir
|
||||
screens/
|
||||
|
||||
# build tools that are often kept/tested locally as well as on the ci machines
|
||||
yoursway-create-dmg/
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
output_tab_size = 2 # new tab size
|
||||
indent_columns = output_tab_size
|
||||
indent_switch_case = output_tab_size
|
||||
indent_with_tabs = 0
|
||||
pp_indent_if = 0 # number
|
||||
pp_if_indent_code = false # false/true
|
||||
pp_define_at_level = false # false/true
|
||||
nl_assign_leave_one_liners = true # false/true
|
||||
nl_class_leave_one_liners = true # false/true
|
||||
nl_enum_leave_one_liners = true # false/true
|
||||
nl_getset_leave_one_liners = true # false/true
|
||||
nl_func_leave_one_liners = true # false/true
|
||||
nl_if_leave_one_liners = true # false/true
|
||||
nl_while_leave_one_liners = true # false/true
|
||||
nl_func_type_name = remove
|
||||
nl_fdef_brace = remove
|
||||
sp_fparen_brace = add
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "../../defc.h"
|
||||
#include "../../protos.h"
|
||||
|
@ -15,13 +15,13 @@
|
|||
#include <string.h>
|
||||
#include "gsportos2.h" /* Resource symbolic identifiers*/
|
||||
|
||||
HAB g_hab; /* PM anchor block handle */
|
||||
PSZ pszErrMsg;
|
||||
HAB g_hab; /* PM anchor block handle */
|
||||
PSZ pszErrMsg;
|
||||
QMSG qmsg; /* Message from message queue */
|
||||
HWND g_hwnd_frame = NULLHANDLE; /* Frame window handle */
|
||||
HWND g_hwnd_client = NULLHANDLE; /* Client area window handle */
|
||||
|
||||
HMQ g_hmq; /* Message queue handle */
|
||||
HMQ g_hmq; /* Message queue handle */
|
||||
|
||||
extern int Verbose;
|
||||
|
||||
|
@ -32,15 +32,15 @@ int g_screen_mdepth = 0;
|
|||
|
||||
extern int g_quit_sim_now;
|
||||
|
||||
int g_use_shmem = 1;
|
||||
int g_has_focus = 0;
|
||||
int g_auto_repeat_on = -1;
|
||||
int g_use_shmem = 1;
|
||||
int g_has_focus = 0;
|
||||
int g_auto_repeat_on = -1;
|
||||
|
||||
extern Kimage g_mainwin_kimage;
|
||||
|
||||
int g_main_height = 0;
|
||||
int g_main_height = 0;
|
||||
|
||||
int g_win_capslock_down = 0;
|
||||
int g_win_capslock_down = 0;
|
||||
|
||||
extern int g_border_sides_refresh_needed;
|
||||
extern int g_border_special_refresh_needed;
|
||||
|
@ -68,87 +68,79 @@ extern char *g_status_ptrs[MAX_STATUS_LINES];
|
|||
|
||||
VOID DispErrorMessage();
|
||||
|
||||
int
|
||||
win_nonblock_read_stdin(int fd, char *bufptr, int len)
|
||||
{
|
||||
int win_nonblock_read_stdin(int fd, char *bufptr, int len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
x_dialog_create_gsport_conf(const char *str)
|
||||
{
|
||||
void x_dialog_create_gsport_conf(const char *str) {
|
||||
}
|
||||
|
||||
int
|
||||
x_show_alert(int is_fatal, const char *str)
|
||||
{
|
||||
return 0;
|
||||
int x_show_alert(int is_fatal, const char *str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
DEVOPENSTRUC pszData;
|
||||
ULONG flCreate; /* Window creation control flags*/
|
||||
int height;
|
||||
SIZEL sizel;
|
||||
int main(int argc, char **argv) {
|
||||
DEVOPENSTRUC pszData;
|
||||
ULONG flCreate; /* Window creation control flags*/
|
||||
int height;
|
||||
SIZEL sizel;
|
||||
|
||||
if ((g_hab = WinInitialize(0)) == 0L) /* Initialize PM */
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
if ((g_hab = WinInitialize(0)) == 0L) /* Initialize PM */
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
|
||||
if ((g_hmq = WinCreateMsgQueue( g_hab, 0 )) == 0L)/* Create a msg queue */
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
if ((g_hmq = WinCreateMsgQueue( g_hab, 0 )) == 0L) /* Create a msg queue */
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
|
||||
if (!WinRegisterClass( /* Register window class */
|
||||
g_hab, /* Anchor block handle */
|
||||
(PSZ)"MyWindow", /* Window class name */
|
||||
(PFNWP)MyWindowProc, /* Address of window procedure */
|
||||
CS_SIZEREDRAW, /* Class style */
|
||||
0 /* No extra window words */
|
||||
))
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
if (!WinRegisterClass( /* Register window class */
|
||||
g_hab, /* Anchor block handle */
|
||||
(PSZ)"MyWindow", /* Window class name */
|
||||
(PFNWP)MyWindowProc, /* Address of window procedure */
|
||||
CS_SIZEREDRAW, /* Class style */
|
||||
0 /* No extra window words */
|
||||
))
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
|
||||
height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES*16);
|
||||
g_main_height = height;
|
||||
height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES*16);
|
||||
g_main_height = height;
|
||||
|
||||
flCreate = FCF_STANDARD & /* Set frame control flags to */
|
||||
~FCF_SHELLPOSITION; /* standard except for shell */
|
||||
/* positioning. */
|
||||
flCreate = FCF_STANDARD & /* Set frame control flags to */
|
||||
~FCF_SHELLPOSITION; /* standard except for shell */
|
||||
/* positioning. */
|
||||
|
||||
if ((g_hwnd_frame = WinCreateStdWindow(
|
||||
HWND_DESKTOP, /* Desktop window is parent */
|
||||
0, /* STD. window styles */
|
||||
&flCreate, /* Frame control flag */
|
||||
"MyWindow", /* Client window class name */
|
||||
"", /* No window text */
|
||||
0, /* No special class style */
|
||||
(HMODULE)0L, /* Resource is in .EXE file */
|
||||
ID_WINDOW, /* Frame window identifier */
|
||||
&g_hwnd_client /* Client window handle */
|
||||
)) == 0L)
|
||||
os2_abort(HWND_DESKTOP, HWND_DESKTOP); /* Terminate the application */
|
||||
if ((g_hwnd_frame = WinCreateStdWindow(
|
||||
HWND_DESKTOP, /* Desktop window is parent */
|
||||
0, /* STD. window styles */
|
||||
&flCreate, /* Frame control flag */
|
||||
"MyWindow", /* Client window class name */
|
||||
"", /* No window text */
|
||||
0, /* No special class style */
|
||||
(HMODULE)0L, /* Resource is in .EXE file */
|
||||
ID_WINDOW, /* Frame window identifier */
|
||||
&g_hwnd_client /* Client window handle */
|
||||
)) == 0L)
|
||||
os2_abort(HWND_DESKTOP, HWND_DESKTOP); /* Terminate the application */
|
||||
|
||||
WinSetWindowText(g_hwnd_frame, "GSport");
|
||||
WinSetWindowText(g_hwnd_frame, "GSport");
|
||||
|
||||
if (!WinSetWindowPos( g_hwnd_frame, /* Shows and activates frame */
|
||||
HWND_TOP, /* window at position 100, 100, */
|
||||
100, 100, X_A2_WINDOW_WIDTH, height, /* and size 200, 200. */
|
||||
SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW
|
||||
))
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
if (!WinSetWindowPos( g_hwnd_frame, /* Shows and activates frame */
|
||||
HWND_TOP, /* window at position 100, 100, */
|
||||
100, 100, X_A2_WINDOW_WIDTH, height, /* and size 200, 200. */
|
||||
SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW
|
||||
))
|
||||
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
|
||||
|
||||
g_hdc_screen = WinOpenWindowDC(g_hwnd_client);
|
||||
sizel.cx = X_A2_WINDOW_WIDTH;
|
||||
sizel.cy = height;
|
||||
g_hps_screen = GpiCreatePS(g_hab,g_hdc_screen, &sizel, PU_PELS | GPIF_LONG | GPIA_ASSOC);
|
||||
g_hdc_screen = WinOpenWindowDC(g_hwnd_client);
|
||||
sizel.cx = X_A2_WINDOW_WIDTH;
|
||||
sizel.cy = height;
|
||||
g_hps_screen = GpiCreatePS(g_hab,g_hdc_screen, &sizel, PU_PELS | GPIF_LONG | GPIA_ASSOC);
|
||||
|
||||
g_hdc_memory = DevOpenDC(g_hab, OD_MEMORY, "*", 4, (PDEVOPENDATA)&pszData, NULL);
|
||||
g_hps_memory = GpiCreatePS(g_hab,g_hdc_memory, &sizel, PU_ARBITRARY | GPIT_MICRO | GPIA_ASSOC);
|
||||
g_hdc_memory = DevOpenDC(g_hab, OD_MEMORY, "*", 4, (PDEVOPENDATA)&pszData, NULL);
|
||||
g_hps_memory = GpiCreatePS(g_hab,g_hdc_memory, &sizel, PU_ARBITRARY | GPIT_MICRO | GPIA_ASSOC);
|
||||
|
||||
// Call gsplusmain
|
||||
return gsplusmain(argc, argv);
|
||||
// Call gsplusmain
|
||||
return gsplusmain(argc, argv);
|
||||
|
||||
}
|
||||
|
||||
|
@ -163,10 +155,9 @@ SIZEL sizel;
|
|||
* the message command and parameters.
|
||||
*
|
||||
*************************************************************************/
|
||||
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
|
||||
{
|
||||
HPS hps;
|
||||
RECTL rcl;
|
||||
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
|
||||
HPS hps;
|
||||
RECTL rcl;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
@ -185,7 +176,7 @@ RECTL rcl;
|
|||
* When Exit is chosen, the application posts itself a WM_CLOSE
|
||||
* message.
|
||||
*/
|
||||
{
|
||||
{
|
||||
USHORT command; /* WM_COMMAND command value */
|
||||
command = SHORT1FROMMP(mp1); /* Extract the command value */
|
||||
switch (command)
|
||||
|
@ -198,7 +189,7 @@ RECTL rcl;
|
|||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
case WM_ERASEBACKGROUND:
|
||||
/*
|
||||
* Return TRUE to request PM to paint the window background
|
||||
|
@ -209,16 +200,16 @@ RECTL rcl;
|
|||
/*
|
||||
* Window contents are drawn here in WM_PAINT processing.
|
||||
*/
|
||||
hps = WinBeginPaint(hwnd, NULLHANDLE, &rcl);
|
||||
WinEndPaint(hps);
|
||||
g_needfullrefreshfornextframe = 1;
|
||||
hps = WinBeginPaint(hwnd, NULLHANDLE, &rcl);
|
||||
WinEndPaint(hps);
|
||||
g_needfullrefreshfornextframe = 1;
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
/*
|
||||
* This is the place to put your termination routines
|
||||
*/
|
||||
WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 ); /* Cause termination*/
|
||||
exit(0);
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
|
@ -232,262 +223,232 @@ RECTL rcl;
|
|||
return (MRESULT)FALSE;
|
||||
} /* End of MyWindowProc */
|
||||
|
||||
void
|
||||
check_input_events()
|
||||
{
|
||||
void check_input_events() {
|
||||
|
||||
/*
|
||||
* Get and dispatch messages from the application message queue
|
||||
* until WinGetMsg returns FALSE, indicating a WM_QUIT message.
|
||||
*/
|
||||
|
||||
while(WinPeekMsg(g_hab, &qmsg, g_hwnd_frame, 0, 0, PM_NOREMOVE)) {
|
||||
if(WinGetMsg(g_hab, &qmsg, 0L, 0, 0) > 0) {
|
||||
//TranslateMessage(&qmsg);
|
||||
WinDispatchMsg(g_hab, &qmsg);
|
||||
} else {
|
||||
printf("GetMessage returned <= 0\n");
|
||||
my_exit(2);
|
||||
}
|
||||
}
|
||||
while(WinPeekMsg(g_hab, &qmsg, g_hwnd_frame, 0, 0, PM_NOREMOVE)) {
|
||||
if(WinGetMsg(g_hab, &qmsg, 0L, 0, 0) > 0) {
|
||||
//TranslateMessage(&qmsg);
|
||||
WinDispatchMsg(g_hab, &qmsg);
|
||||
} else {
|
||||
printf("GetMessage returned <= 0\n");
|
||||
my_exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
|
||||
{
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb) {
|
||||
}
|
||||
|
||||
void
|
||||
x_update_physical_colormap()
|
||||
{
|
||||
void x_update_physical_colormap() {
|
||||
}
|
||||
|
||||
void
|
||||
show_xcolor_array()
|
||||
{
|
||||
void show_xcolor_array() {
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xdriver_end()
|
||||
{
|
||||
printf("OS/2 driver_end\n");
|
||||
void xdriver_end() {
|
||||
printf("OS/2 driver_end\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_get_kimage(Kimage *kimage_ptr)
|
||||
{
|
||||
byte *ptr;
|
||||
int width;
|
||||
int height;
|
||||
int depth, mdepth;
|
||||
int size;
|
||||
void x_get_kimage(Kimage *kimage_ptr) {
|
||||
byte *ptr;
|
||||
int width;
|
||||
int height;
|
||||
int depth, mdepth;
|
||||
int size;
|
||||
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
depth = kimage_ptr->depth;
|
||||
mdepth = kimage_ptr->mdepth;
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
depth = kimage_ptr->depth;
|
||||
mdepth = kimage_ptr->mdepth;
|
||||
|
||||
size = 0;
|
||||
size = 0;
|
||||
|
||||
if(depth == g_screen_depth) {
|
||||
/* Use g_bmapinfo_ptr, adjusting width, height */
|
||||
g_bmaphdr_ptr->cx = width;
|
||||
g_bmaphdr_ptr->cy = height;
|
||||
if(depth == g_screen_depth) {
|
||||
/* Use g_bmapinfo_ptr, adjusting width, height */
|
||||
g_bmaphdr_ptr->cx = width;
|
||||
g_bmaphdr_ptr->cy = height;
|
||||
|
||||
kimage_ptr->dev_handle = GpiCreateBitmap(
|
||||
kimage_ptr->dev_handle = GpiCreateBitmap(
|
||||
|
||||
(HPS)g_hps_memory, (PBITMAPINFOHEADER2)g_bmaphdr_ptr,
|
||||
0L, (PBYTE)kimage_ptr->data_ptr,
|
||||
(PBITMAPINFO2)g_bmapinfo_ptr);
|
||||
(HPS)g_hps_memory, (PBITMAPINFOHEADER2)g_bmaphdr_ptr,
|
||||
0L, (PBYTE)kimage_ptr->data_ptr,
|
||||
(PBITMAPINFO2)g_bmapinfo_ptr);
|
||||
|
||||
size = (width*height*mdepth) >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
size = (width*height*mdepth) >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
printf("malloc for data failed, mdepth: %d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
if(ptr == 0) {
|
||||
printf("malloc for data failed, mdepth: %d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
|
||||
} else {
|
||||
/* allocate buffers for video.c to draw into */
|
||||
} else {
|
||||
/* allocate buffers for video.c to draw into */
|
||||
|
||||
size = (width*height*mdepth) >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
size = (width*height*mdepth) >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
printf("malloc for data failed, mdepth: %d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
if(ptr == 0) {
|
||||
printf("malloc for data failed, mdepth: %d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dev_video_init()
|
||||
{
|
||||
int lores_col;
|
||||
int i;
|
||||
void dev_video_init() {
|
||||
int lores_col;
|
||||
int i;
|
||||
|
||||
printf("Preparing graphics system\n");
|
||||
printf("Preparing graphics system\n");
|
||||
|
||||
g_screen_depth = 24;
|
||||
g_screen_mdepth = 32;
|
||||
g_screen_depth = 24;
|
||||
g_screen_mdepth = 32;
|
||||
|
||||
g_bmapinfo_ptr = (BITMAPINFO2 *)malloc(sizeof(BITMAPINFOHEADER2));
|
||||
g_bmaphdr_ptr = (BITMAPINFOHEADER2 *)g_bmapinfo_ptr;
|
||||
g_bmaphdr_ptr->cbFix = sizeof(BITMAPINFOHEADER2);
|
||||
g_bmaphdr_ptr->cx = A2_WINDOW_WIDTH;
|
||||
g_bmaphdr_ptr->cy = A2_WINDOW_HEIGHT;
|
||||
g_bmaphdr_ptr->cPlanes = 1;
|
||||
g_bmaphdr_ptr->cBitCount = g_screen_mdepth;
|
||||
g_bmaphdr_ptr->ulCompression = BCA_UNCOMP;
|
||||
g_bmaphdr_ptr->cclrUsed = 0;
|
||||
g_bmapinfo_ptr = (BITMAPINFO2 *)malloc(sizeof(BITMAPINFOHEADER2));
|
||||
g_bmaphdr_ptr = (BITMAPINFOHEADER2 *)g_bmapinfo_ptr;
|
||||
g_bmaphdr_ptr->cbFix = sizeof(BITMAPINFOHEADER2);
|
||||
g_bmaphdr_ptr->cx = A2_WINDOW_WIDTH;
|
||||
g_bmaphdr_ptr->cy = A2_WINDOW_HEIGHT;
|
||||
g_bmaphdr_ptr->cPlanes = 1;
|
||||
g_bmaphdr_ptr->cBitCount = g_screen_mdepth;
|
||||
g_bmaphdr_ptr->ulCompression = BCA_UNCOMP;
|
||||
g_bmaphdr_ptr->cclrUsed = 0;
|
||||
|
||||
video_get_kimages();
|
||||
video_get_kimages();
|
||||
|
||||
if(g_screen_depth != 8) {
|
||||
// Allocate g_mainwin_kimage
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
|
||||
g_screen_mdepth);
|
||||
}
|
||||
if(g_screen_depth != 8) {
|
||||
// Allocate g_mainwin_kimage
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
|
||||
g_screen_mdepth);
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
lores_col = g_lores_colors[i & 0xf];
|
||||
video_update_color_raw(i, lores_col);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
for(i = 0; i < 256; i++) {
|
||||
lores_col = g_lores_colors[i & 0xf];
|
||||
video_update_color_raw(i, lores_col);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
|
||||
g_installed_full_superhires_colormap = 1;
|
||||
g_installed_full_superhires_colormap = 1;
|
||||
|
||||
printf("Done with dev_video_init\n");
|
||||
fflush(stdout);
|
||||
printf("Done with dev_video_init\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
x_redraw_status_lines()
|
||||
{
|
||||
void x_redraw_status_lines() {
|
||||
|
||||
int line,len,height;
|
||||
POINTL pt;
|
||||
char *buf;
|
||||
int line,len,height;
|
||||
POINTL pt;
|
||||
char *buf;
|
||||
|
||||
printf("x_redraw_status_lines() called\n");
|
||||
printf("x_redraw_status_lines() called\n");
|
||||
/*
|
||||
if (g_status_ptrs[0] != NULL)
|
||||
{
|
||||
height = 16;
|
||||
pt.x = 5; pt.y = 0;
|
||||
GpiSetColor( g_hps_screen, CLR_NEUTRAL );
|
||||
GpiSetBackColor( g_hps_screen, CLR_BACKGROUND );
|
||||
GpiSetBackMix( g_hps_screen, BM_OVERPAINT );
|
||||
if (g_status_ptrs[0] != NULL)
|
||||
{
|
||||
height = 16;
|
||||
pt.x = 5; pt.y = 0;
|
||||
GpiSetColor( g_hps_screen, CLR_NEUTRAL );
|
||||
GpiSetBackColor( g_hps_screen, CLR_BACKGROUND );
|
||||
GpiSetBackMix( g_hps_screen, BM_OVERPAINT );
|
||||
|
||||
for (line = 0; line < MAX_STATUS_LINES; line++)
|
||||
{
|
||||
buf = g_status_ptrs[line];
|
||||
if (buf != 0)
|
||||
{
|
||||
pt.y = height * (line+1);
|
||||
len = strlen(buf);
|
||||
GpiCharStringAt( g_hps_screen, &pt, (LONG)strlen( buf ), buf );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
for (line = 0; line < MAX_STATUS_LINES; line++)
|
||||
{
|
||||
buf = g_status_ptrs[line];
|
||||
if (buf != 0)
|
||||
{
|
||||
pt.y = height * (line+1);
|
||||
len = strlen(buf);
|
||||
GpiCharStringAt( g_hps_screen, &pt, (LONG)strlen( buf ), buf );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
|
||||
int width, int height)
|
||||
{
|
||||
RECTL rc;
|
||||
POINTL pt[4];
|
||||
HBITMAP hbmOld, hbmNew;
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
|
||||
int width, int height) {
|
||||
RECTL rc;
|
||||
POINTL pt[4];
|
||||
HBITMAP hbmOld, hbmNew;
|
||||
|
||||
char *szString = "Hello, world!\0";
|
||||
char *szString = "Hello, world!\0";
|
||||
|
||||
printf("x_push_kimage() called: Src: (%d,%d) Dest: (%d,%d) Width: %d Height: %d\n",srcx,srcy,destx,desty,width,height);
|
||||
pt[0].x = destx; /* Target X1 */
|
||||
pt[0].y = desty+(MAX_STATUS_LINES*16); /* Target Y1 */
|
||||
pt[1].x = destx+width; /* Target X2 */
|
||||
pt[1].y = desty+height+(MAX_STATUS_LINES*16); /* Target Y2: Translate up, make room for status border */
|
||||
pt[2].x = srcx; /* Source X */
|
||||
pt[2].y = srcy; /* Source Y */
|
||||
pt[3].x = srcx+width;
|
||||
pt[3].y = srcy+height;
|
||||
printf("x_push_kimage() called: Src: (%d,%d) Dest: (%d,%d) Width: %d Height: %d\n",srcx,srcy,destx,desty,width,height);
|
||||
pt[0].x = destx; /* Target X1 */
|
||||
pt[0].y = desty+(MAX_STATUS_LINES*16); /* Target Y1 */
|
||||
pt[1].x = destx+width; /* Target X2 */
|
||||
pt[1].y = desty+height+(MAX_STATUS_LINES*16); /* Target Y2: Translate up, make room for status border */
|
||||
pt[2].x = srcx; /* Source X */
|
||||
pt[2].y = srcy; /* Source Y */
|
||||
pt[3].x = srcx+width;
|
||||
pt[3].y = srcy+height;
|
||||
|
||||
if (width == 560)
|
||||
{
|
||||
/* Paint a known-good bitmap until we can figure out why images aren't showing up */
|
||||
hbmNew = GpiLoadBitmap(g_hps_memory,NULLHANDLE,ID_BITMAP,560,400);
|
||||
hbmOld = GpiSetBitmap(g_hps_memory, hbmNew);
|
||||
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
|
||||
GpiSetBitmap(g_hps_memory, hbmOld);
|
||||
GpiDeleteBitmap(hbmNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
hbmOld = GpiSetBitmap(g_hps_memory, (HBITMAP)kimage_ptr->dev_handle);
|
||||
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
|
||||
GpiSetBitmap(g_hps_memory, hbmOld);
|
||||
}
|
||||
if (width == 560)
|
||||
{
|
||||
/* Paint a known-good bitmap until we can figure out why images aren't showing up */
|
||||
hbmNew = GpiLoadBitmap(g_hps_memory,NULLHANDLE,ID_BITMAP,560,400);
|
||||
hbmOld = GpiSetBitmap(g_hps_memory, hbmNew);
|
||||
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
|
||||
GpiSetBitmap(g_hps_memory, hbmOld);
|
||||
GpiDeleteBitmap(hbmNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
hbmOld = GpiSetBitmap(g_hps_memory, (HBITMAP)kimage_ptr->dev_handle);
|
||||
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
|
||||
GpiSetBitmap(g_hps_memory, hbmOld);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// OG Adding release
|
||||
void x_release_kimage(Kimage* kimage_ptr)
|
||||
{
|
||||
if (kimage_ptr->dev_handle == (void*)-1)
|
||||
{
|
||||
free(kimage_ptr->data_ptr);
|
||||
kimage_ptr->data_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
void x_release_kimage(Kimage* kimage_ptr) {
|
||||
if (kimage_ptr->dev_handle == (void*)-1)
|
||||
{
|
||||
free(kimage_ptr->data_ptr);
|
||||
kimage_ptr->data_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x_push_done()
|
||||
{
|
||||
void x_push_done() {
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_on(int must)
|
||||
{
|
||||
void x_auto_repeat_on(int must) {
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_off(int must)
|
||||
{
|
||||
void x_auto_repeat_off(int must) {
|
||||
}
|
||||
|
||||
void
|
||||
x_hide_pointer(int do_hide)
|
||||
{
|
||||
void x_hide_pointer(int do_hide) {
|
||||
}
|
||||
|
||||
void
|
||||
x_full_screen(int do_full)
|
||||
{
|
||||
return;
|
||||
void x_full_screen(int do_full) {
|
||||
return;
|
||||
}
|
||||
|
||||
int x_calc_ratio(float ratiox,float ratioy)
|
||||
{
|
||||
return 0; // not stretched
|
||||
int x_calc_ratio(float ratiox,float ratioy) {
|
||||
return 0; // not stretched
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
@ -496,33 +457,30 @@ int x_calc_ratio(float ratiox,float ratioy)
|
|||
/* The error message is displayed using a message box */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID DispErrorMessage()
|
||||
{
|
||||
PERRINFO pErrInfoBlk;
|
||||
PSZ pszOffSet, pszErrMsg;
|
||||
ERRORID ErrorId;
|
||||
PCH ErrorStr;
|
||||
VOID DispErrorMessage() {
|
||||
PERRINFO pErrInfoBlk;
|
||||
PSZ pszOffSet, pszErrMsg;
|
||||
ERRORID ErrorId;
|
||||
PCH ErrorStr;
|
||||
|
||||
ErrorId = WinGetLastError(g_hab);
|
||||
ErrorId = WinGetLastError(g_hab);
|
||||
|
||||
if ((pErrInfoBlk = WinGetErrorInfo(g_hab)) != (PERRINFO)NULL)
|
||||
{
|
||||
pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
|
||||
pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet);
|
||||
if ((pErrInfoBlk = WinGetErrorInfo(g_hab)) != (PERRINFO)NULL)
|
||||
{
|
||||
pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
|
||||
pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet);
|
||||
|
||||
WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
|
||||
g_hwnd_frame, /* Owner window is our frame */
|
||||
pszErrMsg, /* PMWIN Error message */
|
||||
"Error", /* Title bar message */
|
||||
0, /* Message identifier */
|
||||
MB_MOVEABLE | MB_CANCEL ); /* Flags */
|
||||
WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
|
||||
g_hwnd_frame, /* Owner window is our frame */
|
||||
pszErrMsg, /* PMWIN Error message */
|
||||
"Error", /* Title bar message */
|
||||
0, /* Message identifier */
|
||||
MB_MOVEABLE | MB_CANCEL ); /* Flags */
|
||||
|
||||
WinFreeErrorInfo(pErrInfoBlk);
|
||||
}
|
||||
WinFreeErrorInfo(pErrInfoBlk);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
os2_abort(HWND g_hwnd_frame, HWND g_hwnd_client)
|
||||
{
|
||||
void os2_abort(HWND g_hwnd_frame, HWND g_hwnd_client) {
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
int g_preferred_rate = 48000;
|
||||
|
|
|
@ -18,48 +18,45 @@
|
|||
* 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "dirport.h"
|
||||
|
||||
DIR *opendir (char *path)
|
||||
{
|
||||
APIRET ulrc;
|
||||
ULONG cnt = 1;
|
||||
DIR *dir;
|
||||
char *name;
|
||||
|
||||
if (!(dir = (DIR*)calloc(1, sizeof(DIR)))) {
|
||||
return NULL;
|
||||
}
|
||||
if (name = (char*)calloc(1, strlen(path) + 3)) {
|
||||
strcat(strcpy(name, path),path[strlen(path) - 1] == '\\' ? "*" : "\\*");
|
||||
dir->handle = HDIR_CREATE;
|
||||
ulrc = DosFindFirst(name, &(dir->handle), _A_ANY, &(dir->buffer), sizeof(struct _FILEFINDBUF3), &cnt, FIL_STANDARD);
|
||||
free(name);
|
||||
}
|
||||
if (!name || ulrc) {
|
||||
DosFindClose (dir->handle);
|
||||
free(dir);
|
||||
dir = NULL;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
struct dirent *readdir (DIR *dir)
|
||||
{
|
||||
ULONG cnt = 1;
|
||||
|
||||
return DosFindNext (dir->handle, &(dir->buffer), sizeof(struct _FILEFINDBUF), &cnt) ? NULL : &(dir->buffer);
|
||||
}
|
||||
|
||||
int closedir (DIR *dir)
|
||||
{
|
||||
APIRET ulrc = DosFindClose (dir->handle);
|
||||
DIR *opendir (char *path) {
|
||||
APIRET ulrc;
|
||||
ULONG cnt = 1;
|
||||
DIR *dir;
|
||||
char *name;
|
||||
|
||||
if (!(dir = (DIR*)calloc(1, sizeof(DIR)))) {
|
||||
return NULL;
|
||||
}
|
||||
if (name = (char*)calloc(1, strlen(path) + 3)) {
|
||||
strcat(strcpy(name, path),path[strlen(path) - 1] == '\\' ? "*" : "\\*");
|
||||
dir->handle = HDIR_CREATE;
|
||||
ulrc = DosFindFirst(name, &(dir->handle), _A_ANY, &(dir->buffer), sizeof(struct _FILEFINDBUF3), &cnt, FIL_STANDARD);
|
||||
free(name);
|
||||
}
|
||||
if (!name || ulrc) {
|
||||
DosFindClose (dir->handle);
|
||||
free(dir);
|
||||
return (int)ulrc;
|
||||
dir = NULL;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
struct dirent *readdir (DIR *dir) {
|
||||
ULONG cnt = 1;
|
||||
|
||||
return DosFindNext (dir->handle, &(dir->buffer), sizeof(struct _FILEFINDBUF), &cnt) ? NULL : &(dir->buffer);
|
||||
}
|
||||
|
||||
int closedir (DIR *dir) {
|
||||
APIRET ulrc = DosFindClose (dir->handle);
|
||||
|
||||
free(dir);
|
||||
return (int)ulrc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,7 +68,7 @@ int closedir (DIR *dir)
|
|||
snprintf.c
|
||||
- a portable implementation of snprintf,
|
||||
including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
|
||||
|
||||
|
||||
snprintf is a routine to convert numeric and string arguments to
|
||||
formatted strings. It is similar to sprintf(3) provided in a system's
|
||||
C library, yet it requires an additional argument - the buffer size -
|
||||
|
@ -81,10 +78,10 @@ int closedir (DIR *dir)
|
|||
not or do provide an inadequate (slow or idiosyncratic) version, which
|
||||
calls for a portable implementation of this routine.
|
||||
|
||||
Author
|
||||
Author
|
||||
|
||||
Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
|
||||
Copyright © 1999, Mark Martinec
|
||||
Copyright <EFBFBD> 1999, Mark Martinec
|
||||
|
||||
*/
|
||||
|
||||
|
@ -167,14 +164,14 @@ Author
|
|||
#define fast_memcpy(d,s,n) \
|
||||
{ register size_t nn = (size_t)(n); \
|
||||
if (nn >= breakeven_point) memcpy((d), (s), nn); \
|
||||
else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
|
||||
else if (nn > 0) { /* proc call overhead is worth only for large strings*/ \
|
||||
register char *dd; register const char *ss; \
|
||||
for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
|
||||
|
||||
#define fast_memset(d,c,n) \
|
||||
{ register size_t nn = (size_t)(n); \
|
||||
if (nn >= breakeven_point) memset((d), (int)(c), nn); \
|
||||
else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
|
||||
else if (nn > 0) { /* proc call overhead is worth only for large strings*/ \
|
||||
register char *dd; register const int cc=(int)(c); \
|
||||
for (dd=(d); nn>0; nn--) *dd++ = cc; } }
|
||||
|
||||
|
@ -251,8 +248,7 @@ int vasprintf(char **ptr, const char *fmt, va_list ap) {
|
|||
{ va_list ap2;
|
||||
va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */
|
||||
str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
|
||||
va_end(ap2);
|
||||
}
|
||||
va_end(ap2);}
|
||||
assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
|
||||
*ptr = (char *) malloc(str_m = (size_t)str_l + 1);
|
||||
if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
|
||||
|
@ -300,8 +296,7 @@ int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) {
|
|||
{ va_list ap2;
|
||||
va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */
|
||||
str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
|
||||
va_end(ap2);
|
||||
}
|
||||
va_end(ap2);}
|
||||
assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
|
||||
if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */
|
||||
/* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
|
||||
|
@ -358,14 +353,14 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
if (!p) p = "";
|
||||
while (*p) {
|
||||
if (*p != '%') {
|
||||
/* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */
|
||||
/* but the following code achieves better performance for cases
|
||||
* where format string is long and contains few conversions */
|
||||
/* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */
|
||||
/* but the following code achieves better performance for cases
|
||||
* where format string is long and contains few conversions */
|
||||
const char *q = strchr(p+1,'%');
|
||||
size_t n = !q ? strlen(p) : (q-p);
|
||||
if (str_l < str_m) {
|
||||
size_t avail = str_m-str_l;
|
||||
fast_memcpy(str+str_l, p, (n>avail?avail:n));
|
||||
fast_memcpy(str+str_l, p, (n>avail ? avail : n));
|
||||
}
|
||||
p += n; str_l += n;
|
||||
} else {
|
||||
|
@ -382,45 +377,45 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
size_t str_arg_l; /* natural field width of arg without padding
|
||||
and sign */
|
||||
unsigned char uchar_arg;
|
||||
/* unsigned char argument value - only defined for c conversion.
|
||||
N.B. standard explicitly states the char argument for
|
||||
the c conversion is unsigned */
|
||||
/* unsigned char argument value - only defined for c conversion.
|
||||
N.B. standard explicitly states the char argument for
|
||||
the c conversion is unsigned */
|
||||
|
||||
size_t number_of_zeros_to_pad = 0;
|
||||
/* number of zeros to be inserted for numeric conversions
|
||||
as required by the precision or minimal field width */
|
||||
/* number of zeros to be inserted for numeric conversions
|
||||
as required by the precision or minimal field width */
|
||||
|
||||
size_t zero_padding_insertion_ind = 0;
|
||||
/* index into tmp where zero padding is to be inserted */
|
||||
/* index into tmp where zero padding is to be inserted */
|
||||
|
||||
char fmt_spec = '\0';
|
||||
/* current conversion specifier character */
|
||||
/* current conversion specifier character */
|
||||
|
||||
str_arg = credits;/* just to make compiler happy (defined but not used)*/
|
||||
str_arg = NULL;
|
||||
starting_p = p; p++; /* skip '%' */
|
||||
/* parse flags */
|
||||
/* parse flags */
|
||||
while (*p == '0' || *p == '-' || *p == '+' ||
|
||||
*p == ' ' || *p == '#' || *p == '\'') {
|
||||
switch (*p) {
|
||||
case '0': zero_padding = 1; break;
|
||||
case '-': justify_left = 1; break;
|
||||
case '+': force_sign = 1; space_for_positive = 0; break;
|
||||
case ' ': force_sign = 1;
|
||||
/* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
|
||||
case '0': zero_padding = 1; break;
|
||||
case '-': justify_left = 1; break;
|
||||
case '+': force_sign = 1; space_for_positive = 0; break;
|
||||
case ' ': force_sign = 1;
|
||||
/* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
|
||||
#ifdef PERL_COMPATIBLE
|
||||
/* ... but in Perl the last of ' ' and '+' applies */
|
||||
space_for_positive = 1;
|
||||
/* ... but in Perl the last of ' ' and '+' applies */
|
||||
space_for_positive = 1;
|
||||
#endif
|
||||
break;
|
||||
case '#': alternate_form = 1; break;
|
||||
case '\'': break;
|
||||
break;
|
||||
case '#': alternate_form = 1; break;
|
||||
case '\'': break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
/* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
|
||||
/* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
|
||||
|
||||
/* parse field width */
|
||||
/* parse field width */
|
||||
if (*p == '*') {
|
||||
int j;
|
||||
p++; j = va_arg(ap, int);
|
||||
|
@ -433,7 +428,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
|
||||
min_field_width = uj;
|
||||
}
|
||||
/* parse precision */
|
||||
/* parse precision */
|
||||
if (*p == '.') {
|
||||
p++; precision_specified = 1;
|
||||
if (*p == '*') {
|
||||
|
@ -442,12 +437,12 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
if (j >= 0) precision = j;
|
||||
else {
|
||||
precision_specified = 0; precision = 0;
|
||||
/* NOTE:
|
||||
* Solaris 2.6 man page claims that in this case the precision
|
||||
* should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page
|
||||
* claim that this case should be treated as unspecified precision,
|
||||
* which is what we do here.
|
||||
*/
|
||||
/* NOTE:
|
||||
* Solaris 2.6 man page claims that in this case the precision
|
||||
* should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page
|
||||
* claim that this case should be treated as unspecified precision,
|
||||
* which is what we do here.
|
||||
*/
|
||||
}
|
||||
} else if (isdigit((int)(*p))) {
|
||||
/* size_t could be wider than unsigned int;
|
||||
|
@ -457,7 +452,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
precision = uj;
|
||||
}
|
||||
}
|
||||
/* parse 'h', 'l' and 'll' length modifiers */
|
||||
/* parse 'h', 'l' and 'll' length modifiers */
|
||||
if (*p == 'h' || *p == 'l') {
|
||||
length_modifier = *p; p++;
|
||||
if (length_modifier == 'l' && *p == 'l') { /* double l = long long */
|
||||
|
@ -470,336 +465,334 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
}
|
||||
}
|
||||
fmt_spec = *p;
|
||||
/* common synonyms: */
|
||||
/* common synonyms: */
|
||||
switch (fmt_spec) {
|
||||
case 'i': fmt_spec = 'd'; break;
|
||||
case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
|
||||
case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
|
||||
case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
|
||||
default: break;
|
||||
case 'i': fmt_spec = 'd'; break;
|
||||
case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
|
||||
case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
|
||||
case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
|
||||
default: break;
|
||||
}
|
||||
/* get parameter value, do initial processing */
|
||||
/* get parameter value, do initial processing */
|
||||
switch (fmt_spec) {
|
||||
case '%': /* % behaves similar to 's' regarding flags and field widths */
|
||||
case 'c': /* c behaves similar to 's' regarding flags and field widths */
|
||||
case 's':
|
||||
length_modifier = '\0'; /* wint_t and wchar_t not supported */
|
||||
/* the result of zero padding flag with non-numeric conversion specifier*/
|
||||
/* is undefined. Solaris and HPUX 10 does zero padding in this case, */
|
||||
/* Digital Unix and Linux does not. */
|
||||
#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
|
||||
zero_padding = 0; /* turn zero padding off for string conversions */
|
||||
#endif
|
||||
str_arg_l = 1;
|
||||
switch (fmt_spec) {
|
||||
case '%':
|
||||
str_arg = p; break;
|
||||
case 'c': {
|
||||
int j = va_arg(ap, int);
|
||||
uchar_arg = (unsigned char) j; /* standard demands unsigned char */
|
||||
str_arg = (const char *) &uchar_arg;
|
||||
break;
|
||||
}
|
||||
case '%': /* % behaves similar to 's' regarding flags and field widths */
|
||||
case 'c': /* c behaves similar to 's' regarding flags and field widths */
|
||||
case 's':
|
||||
str_arg = va_arg(ap, const char *);
|
||||
if (!str_arg) str_arg_l = 0;
|
||||
/* make sure not to address string beyond the specified precision !!! */
|
||||
else if (!precision_specified) str_arg_l = strlen(str_arg);
|
||||
/* truncate string if necessary as requested by precision */
|
||||
else if (precision == 0) str_arg_l = 0;
|
||||
else {
|
||||
/* memchr on HP does not like n > 2^31 !!! */
|
||||
const char *q = memchr(str_arg, '\0',
|
||||
precision <= 0x7fffffff ? precision : 0x7fffffff);
|
||||
str_arg_l = !q ? precision : (q-str_arg);
|
||||
length_modifier = '\0'; /* wint_t and wchar_t not supported */
|
||||
/* the result of zero padding flag with non-numeric conversion specifier*/
|
||||
/* is undefined. Solaris and HPUX 10 does zero padding in this case, */
|
||||
/* Digital Unix and Linux does not. */
|
||||
#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
|
||||
zero_padding = 0; /* turn zero padding off for string conversions */
|
||||
#endif
|
||||
str_arg_l = 1;
|
||||
switch (fmt_spec) {
|
||||
case '%':
|
||||
str_arg = p; break;
|
||||
case 'c': {
|
||||
int j = va_arg(ap, int);
|
||||
uchar_arg = (unsigned char) j; /* standard demands unsigned char */
|
||||
str_arg = (const char *) &uchar_arg;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
str_arg = va_arg(ap, const char *);
|
||||
if (!str_arg) str_arg_l = 0;
|
||||
/* make sure not to address string beyond the specified precision !!! */
|
||||
else if (!precision_specified) str_arg_l = strlen(str_arg);
|
||||
/* truncate string if necessary as requested by precision */
|
||||
else if (precision == 0) str_arg_l = 0;
|
||||
else {
|
||||
/* memchr on HP does not like n > 2^31 !!! */
|
||||
const char *q = memchr(str_arg, '\0',
|
||||
precision <= 0x7fffffff ? precision : 0x7fffffff);
|
||||
str_arg_l = !q ? precision : (q-str_arg);
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
|
||||
/* NOTE: the u, o, x, X and p conversion specifiers imply
|
||||
the value is unsigned; d implies a signed value */
|
||||
case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
|
||||
/* NOTE: the u, o, x, X and p conversion specifiers imply
|
||||
the value is unsigned; d implies a signed value */
|
||||
|
||||
int arg_sign = 0;
|
||||
int arg_sign = 0;
|
||||
/* 0 if numeric argument is zero (or if pointer is NULL for 'p'),
|
||||
+1 if greater than zero (or nonzero for unsigned arguments),
|
||||
-1 if negative (unsigned argument is never negative) */
|
||||
+1 if greater than zero (or nonzero for unsigned arguments),
|
||||
-1 if negative (unsigned argument is never negative) */
|
||||
|
||||
int int_arg = 0; unsigned int uint_arg = 0;
|
||||
int int_arg = 0; unsigned int uint_arg = 0;
|
||||
/* only defined for length modifier h, or for no length modifiers */
|
||||
|
||||
long int long_arg = 0; unsigned long int ulong_arg = 0;
|
||||
long int long_arg = 0; unsigned long int ulong_arg = 0;
|
||||
/* only defined for length modifier l */
|
||||
|
||||
void *ptr_arg = NULL;
|
||||
void *ptr_arg = NULL;
|
||||
/* pointer argument value -only defined for p conversion */
|
||||
|
||||
#ifdef SNPRINTF_LONGLONG_SUPPORT
|
||||
long long int long_long_arg = 0;
|
||||
unsigned long long int ulong_long_arg = 0;
|
||||
long long int long_long_arg = 0;
|
||||
unsigned long long int ulong_long_arg = 0;
|
||||
/* only defined for length modifier ll */
|
||||
#endif
|
||||
if (fmt_spec == 'p') {
|
||||
/* HPUX 10: An l, h, ll or L before any other conversion character
|
||||
* (other than d, i, u, o, x, or X) is ignored.
|
||||
* Digital Unix:
|
||||
* not specified, but seems to behave as HPUX does.
|
||||
* Solaris: If an h, l, or L appears before any other conversion
|
||||
* specifier (other than d, i, u, o, x, or X), the behavior
|
||||
* is undefined. (Actually %hp converts only 16-bits of address
|
||||
* and %llp treats address as 64-bit data which is incompatible
|
||||
* with (void *) argument on a 32-bit system).
|
||||
*/
|
||||
if (fmt_spec == 'p') {
|
||||
/* HPUX 10: An l, h, ll or L before any other conversion character
|
||||
* (other than d, i, u, o, x, or X) is ignored.
|
||||
* Digital Unix:
|
||||
* not specified, but seems to behave as HPUX does.
|
||||
* Solaris: If an h, l, or L appears before any other conversion
|
||||
* specifier (other than d, i, u, o, x, or X), the behavior
|
||||
* is undefined. (Actually %hp converts only 16-bits of address
|
||||
* and %llp treats address as 64-bit data which is incompatible
|
||||
* with (void *) argument on a 32-bit system).
|
||||
*/
|
||||
#ifdef SOLARIS_COMPATIBLE
|
||||
# ifdef SOLARIS_BUG_COMPATIBLE
|
||||
/* keep length modifiers even if it represents 'll' */
|
||||
/* keep length modifiers even if it represents 'll' */
|
||||
# else
|
||||
if (length_modifier == '2') length_modifier = '\0';
|
||||
if (length_modifier == '2') length_modifier = '\0';
|
||||
# endif
|
||||
#else
|
||||
length_modifier = '\0';
|
||||
length_modifier = '\0';
|
||||
#endif
|
||||
ptr_arg = va_arg(ap, void *);
|
||||
if (ptr_arg != NULL) arg_sign = 1;
|
||||
} else if (fmt_spec == 'd') { /* signed */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h':
|
||||
/* It is non-portable to specify a second argument of char or short
|
||||
* to va_arg, because arguments seen by the called function
|
||||
* are not char or short. C converts char and short arguments
|
||||
* to int before passing them to a function.
|
||||
*/
|
||||
int_arg = va_arg(ap, int);
|
||||
if (int_arg > 0) arg_sign = 1;
|
||||
else if (int_arg < 0) arg_sign = -1;
|
||||
break;
|
||||
case 'l':
|
||||
long_arg = va_arg(ap, long int);
|
||||
if (long_arg > 0) arg_sign = 1;
|
||||
else if (long_arg < 0) arg_sign = -1;
|
||||
break;
|
||||
ptr_arg = va_arg(ap, void *);
|
||||
if (ptr_arg != NULL) arg_sign = 1;
|
||||
} else if (fmt_spec == 'd') { /* signed */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h':
|
||||
/* It is non-portable to specify a second argument of char or short
|
||||
* to va_arg, because arguments seen by the called function
|
||||
* are not char or short. C converts char and short arguments
|
||||
* to int before passing them to a function.
|
||||
*/
|
||||
int_arg = va_arg(ap, int);
|
||||
if (int_arg > 0) arg_sign = 1;
|
||||
else if (int_arg < 0) arg_sign = -1;
|
||||
break;
|
||||
case 'l':
|
||||
long_arg = va_arg(ap, long int);
|
||||
if (long_arg > 0) arg_sign = 1;
|
||||
else if (long_arg < 0) arg_sign = -1;
|
||||
break;
|
||||
#ifdef SNPRINTF_LONGLONG_SUPPORT
|
||||
case '2':
|
||||
long_long_arg = va_arg(ap, long long int);
|
||||
if (long_long_arg > 0) arg_sign = 1;
|
||||
else if (long_long_arg < 0) arg_sign = -1;
|
||||
break;
|
||||
case '2':
|
||||
long_long_arg = va_arg(ap, long long int);
|
||||
if (long_long_arg > 0) arg_sign = 1;
|
||||
else if (long_long_arg < 0) arg_sign = -1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
} else { /* unsigned */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h':
|
||||
uint_arg = va_arg(ap, unsigned int);
|
||||
if (uint_arg) arg_sign = 1;
|
||||
break;
|
||||
case 'l':
|
||||
ulong_arg = va_arg(ap, unsigned long int);
|
||||
if (ulong_arg) arg_sign = 1;
|
||||
break;
|
||||
}
|
||||
} else { /* unsigned */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h':
|
||||
uint_arg = va_arg(ap, unsigned int);
|
||||
if (uint_arg) arg_sign = 1;
|
||||
break;
|
||||
case 'l':
|
||||
ulong_arg = va_arg(ap, unsigned long int);
|
||||
if (ulong_arg) arg_sign = 1;
|
||||
break;
|
||||
#ifdef SNPRINTF_LONGLONG_SUPPORT
|
||||
case '2':
|
||||
ulong_long_arg = va_arg(ap, unsigned long long int);
|
||||
if (ulong_long_arg) arg_sign = 1;
|
||||
break;
|
||||
case '2':
|
||||
ulong_long_arg = va_arg(ap, unsigned long long int);
|
||||
if (ulong_long_arg) arg_sign = 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
str_arg = tmp; str_arg_l = 0;
|
||||
/* NOTE:
|
||||
* For d, i, u, o, x, and X conversions, if precision is specified,
|
||||
* the '0' flag should be ignored. This is so with Solaris 2.6,
|
||||
* Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
|
||||
*/
|
||||
str_arg = tmp; str_arg_l = 0;
|
||||
/* NOTE:
|
||||
* For d, i, u, o, x, and X conversions, if precision is specified,
|
||||
* the '0' flag should be ignored. This is so with Solaris 2.6,
|
||||
* Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
|
||||
*/
|
||||
#ifndef PERL_COMPATIBLE
|
||||
if (precision_specified) zero_padding = 0;
|
||||
if (precision_specified) zero_padding = 0;
|
||||
#endif
|
||||
if (fmt_spec == 'd') {
|
||||
if (force_sign && arg_sign >= 0)
|
||||
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
|
||||
/* leave negative numbers for sprintf to handle,
|
||||
to avoid handling tricky cases like (short int)(-32768) */
|
||||
if (fmt_spec == 'd') {
|
||||
if (force_sign && arg_sign >= 0)
|
||||
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
|
||||
/* leave negative numbers for sprintf to handle,
|
||||
to avoid handling tricky cases like (short int)(-32768) */
|
||||
#ifdef LINUX_COMPATIBLE
|
||||
} else if (fmt_spec == 'p' && force_sign && arg_sign > 0) {
|
||||
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
|
||||
} else if (fmt_spec == 'p' && force_sign && arg_sign > 0) {
|
||||
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
|
||||
#endif
|
||||
} else if (alternate_form) {
|
||||
if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
|
||||
} else if (alternate_form) {
|
||||
if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
|
||||
{ tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; }
|
||||
/* alternate form should have no effect for p conversion, but ... */
|
||||
/* alternate form should have no effect for p conversion, but ... */
|
||||
#ifdef HPUX_COMPATIBLE
|
||||
else if (fmt_spec == 'p'
|
||||
/* HPUX 10: for an alternate form of p conversion,
|
||||
* a nonzero result is prefixed by 0x. */
|
||||
else if (fmt_spec == 'p'
|
||||
/* HPUX 10: for an alternate form of p conversion,
|
||||
* a nonzero result is prefixed by 0x. */
|
||||
#ifndef HPUX_BUG_COMPATIBLE
|
||||
/* Actually it uses 0x prefix even for a zero value. */
|
||||
&& arg_sign != 0
|
||||
/* Actually it uses 0x prefix even for a zero value. */
|
||||
&& arg_sign != 0
|
||||
#endif
|
||||
) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; }
|
||||
) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; }
|
||||
#endif
|
||||
}
|
||||
zero_padding_insertion_ind = str_arg_l;
|
||||
if (!precision_specified) precision = 1; /* default precision is 1 */
|
||||
if (precision == 0 && arg_sign == 0
|
||||
}
|
||||
zero_padding_insertion_ind = str_arg_l;
|
||||
if (!precision_specified) precision = 1; /* default precision is 1 */
|
||||
if (precision == 0 && arg_sign == 0
|
||||
#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE)
|
||||
&& fmt_spec != 'p'
|
||||
/* HPUX 10 man page claims: With conversion character p the result of
|
||||
* converting a zero value with a precision of zero is a null string.
|
||||
* Actually HP returns all zeroes, and Linux returns "(nil)". */
|
||||
&& fmt_spec != 'p'
|
||||
/* HPUX 10 man page claims: With conversion character p the result of
|
||||
* converting a zero value with a precision of zero is a null string.
|
||||
* Actually HP returns all zeroes, and Linux returns "(nil)". */
|
||||
#endif
|
||||
) {
|
||||
/* converted to null string */
|
||||
/* When zero value is formatted with an explicit precision 0,
|
||||
the resulting formatted string is empty (d, i, u, o, x, X, p). */
|
||||
} else {
|
||||
char f[5]; int f_l = 0;
|
||||
f[f_l++] = '%'; /* construct a simple format string for sprintf */
|
||||
if (!length_modifier) { }
|
||||
else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
|
||||
else f[f_l++] = length_modifier;
|
||||
f[f_l++] = fmt_spec; f[f_l++] = '\0';
|
||||
if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
|
||||
else if (fmt_spec == 'd') { /* signed */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break;
|
||||
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
|
||||
) {
|
||||
/* converted to null string */
|
||||
/* When zero value is formatted with an explicit precision 0,
|
||||
the resulting formatted string is empty (d, i, u, o, x, X, p). */
|
||||
} else {
|
||||
char f[5]; int f_l = 0;
|
||||
f[f_l++] = '%'; /* construct a simple format string for sprintf */
|
||||
if (!length_modifier) { }
|
||||
else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
|
||||
else f[f_l++] = length_modifier;
|
||||
f[f_l++] = fmt_spec; f[f_l++] = '\0';
|
||||
if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
|
||||
else if (fmt_spec == 'd') { /* signed */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break;
|
||||
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
|
||||
#ifdef SNPRINTF_LONGLONG_SUPPORT
|
||||
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
|
||||
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
|
||||
#endif
|
||||
}
|
||||
} else { /* unsigned */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break;
|
||||
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
|
||||
#ifdef SNPRINTF_LONGLONG_SUPPORT
|
||||
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else { /* unsigned */
|
||||
switch (length_modifier) {
|
||||
case '\0':
|
||||
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break;
|
||||
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
|
||||
#ifdef SNPRINTF_LONGLONG_SUPPORT
|
||||
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break;
|
||||
#endif
|
||||
/* include the optional minus sign and possible "0x"
|
||||
in the region before the zero padding insertion point */
|
||||
if (zero_padding_insertion_ind < str_arg_l &&
|
||||
tmp[zero_padding_insertion_ind] == '-') {
|
||||
zero_padding_insertion_ind++;
|
||||
}
|
||||
if (zero_padding_insertion_ind+1 < str_arg_l &&
|
||||
tmp[zero_padding_insertion_ind] == '0' &&
|
||||
(tmp[zero_padding_insertion_ind+1] == 'x' ||
|
||||
tmp[zero_padding_insertion_ind+1] == 'X') ) {
|
||||
zero_padding_insertion_ind += 2;
|
||||
}
|
||||
}
|
||||
/* include the optional minus sign and possible "0x"
|
||||
in the region before the zero padding insertion point */
|
||||
if (zero_padding_insertion_ind < str_arg_l &&
|
||||
tmp[zero_padding_insertion_ind] == '-') {
|
||||
zero_padding_insertion_ind++;
|
||||
}
|
||||
if (zero_padding_insertion_ind+1 < str_arg_l &&
|
||||
tmp[zero_padding_insertion_ind] == '0' &&
|
||||
(tmp[zero_padding_insertion_ind+1] == 'x' ||
|
||||
tmp[zero_padding_insertion_ind+1] == 'X') ) {
|
||||
zero_padding_insertion_ind += 2;
|
||||
}
|
||||
}
|
||||
{ size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
|
||||
if (alternate_form && fmt_spec == 'o'
|
||||
{ size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
|
||||
if (alternate_form && fmt_spec == 'o'
|
||||
#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */
|
||||
&& (str_arg_l > 0)
|
||||
&& (str_arg_l > 0)
|
||||
#endif
|
||||
#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */
|
||||
#else
|
||||
/* unless zero is already the first character */
|
||||
&& !(zero_padding_insertion_ind < str_arg_l
|
||||
&& tmp[zero_padding_insertion_ind] == '0')
|
||||
/* unless zero is already the first character */
|
||||
&& !(zero_padding_insertion_ind < str_arg_l
|
||||
&& tmp[zero_padding_insertion_ind] == '0')
|
||||
#endif
|
||||
) { /* assure leading zero for alternate-form octal numbers */
|
||||
if (!precision_specified || precision < num_of_digits+1) {
|
||||
/* precision is increased to force the first character to be zero,
|
||||
except if a zero value is formatted with an explicit precision
|
||||
of zero */
|
||||
precision = num_of_digits+1; precision_specified = 1;
|
||||
) { /* assure leading zero for alternate-form octal numbers */
|
||||
if (!precision_specified || precision < num_of_digits+1) {
|
||||
/* precision is increased to force the first character to be zero,
|
||||
except if a zero value is formatted with an explicit precision
|
||||
of zero */
|
||||
precision = num_of_digits+1; precision_specified = 1;
|
||||
}
|
||||
}
|
||||
/* zero padding to specified precision? */
|
||||
if (num_of_digits < precision)
|
||||
number_of_zeros_to_pad = precision - num_of_digits; }
|
||||
/* zero padding to specified minimal field width? */
|
||||
if (!justify_left && zero_padding) {
|
||||
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
|
||||
if (n > 0) number_of_zeros_to_pad += n;
|
||||
}
|
||||
/* zero padding to specified precision? */
|
||||
if (num_of_digits < precision)
|
||||
number_of_zeros_to_pad = precision - num_of_digits;
|
||||
break;
|
||||
}
|
||||
/* zero padding to specified minimal field width? */
|
||||
if (!justify_left && zero_padding) {
|
||||
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
|
||||
if (n > 0) number_of_zeros_to_pad += n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: /* unrecognized conversion specifier, keep format string as-is*/
|
||||
zero_padding = 0; /* turn zero padding off for non-numeric convers. */
|
||||
default: /* unrecognized conversion specifier, keep format string as-is*/
|
||||
zero_padding = 0; /* turn zero padding off for non-numeric convers. */
|
||||
#ifndef DIGITAL_UNIX_COMPATIBLE
|
||||
justify_left = 1; min_field_width = 0; /* reset flags */
|
||||
justify_left = 1; min_field_width = 0; /* reset flags */
|
||||
#endif
|
||||
#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE)
|
||||
/* keep the entire format string unchanged */
|
||||
str_arg = starting_p; str_arg_l = p - starting_p;
|
||||
/* well, not exactly so for Linux, which does something inbetween,
|
||||
* and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */
|
||||
/* keep the entire format string unchanged */
|
||||
str_arg = starting_p; str_arg_l = p - starting_p;
|
||||
/* well, not exactly so for Linux, which does something inbetween,
|
||||
* and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */
|
||||
#else
|
||||
/* discard the unrecognized conversion, just keep *
|
||||
* the unrecognized conversion character */
|
||||
str_arg = p; str_arg_l = 0;
|
||||
/* discard the unrecognized conversion, just keep *
|
||||
* the unrecognized conversion character */
|
||||
str_arg = p; str_arg_l = 0;
|
||||
#endif
|
||||
if (*p) str_arg_l++; /* include invalid conversion specifier unchanged
|
||||
if not at end-of-string */
|
||||
break;
|
||||
if (*p) str_arg_l++; /* include invalid conversion specifier unchanged
|
||||
if not at end-of-string */
|
||||
break;
|
||||
}
|
||||
if (*p) p++; /* step over the just processed conversion specifier */
|
||||
/* insert padding to the left as requested by min_field_width;
|
||||
this does not include the zero padding in case of numerical conversions*/
|
||||
/* insert padding to the left as requested by min_field_width;
|
||||
this does not include the zero padding in case of numerical conversions*/
|
||||
if (!justify_left) { /* left padding with blank or zero */
|
||||
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
|
||||
if (n > 0) {
|
||||
if (str_l < str_m) {
|
||||
size_t avail = str_m-str_l;
|
||||
fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n));
|
||||
fast_memset(str+str_l, (zero_padding ? '0' : ' '), (n>avail ? avail : n));
|
||||
}
|
||||
str_l += n;
|
||||
}
|
||||
}
|
||||
/* zero padding as requested by the precision or by the minimal field width
|
||||
* for numeric conversions required? */
|
||||
/* zero padding as requested by the precision or by the minimal field width
|
||||
* for numeric conversions required? */
|
||||
if (number_of_zeros_to_pad <= 0) {
|
||||
/* will not copy first part of numeric right now, *
|
||||
* force it to be copied later in its entirety */
|
||||
/* will not copy first part of numeric right now, *
|
||||
* force it to be copied later in its entirety */
|
||||
zero_padding_insertion_ind = 0;
|
||||
} else {
|
||||
/* insert first part of numerics (sign or '0x') before zero padding */
|
||||
/* insert first part of numerics (sign or '0x') before zero padding */
|
||||
int n = zero_padding_insertion_ind;
|
||||
if (n > 0) {
|
||||
if (str_l < str_m) {
|
||||
size_t avail = str_m-str_l;
|
||||
fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
|
||||
fast_memcpy(str+str_l, str_arg, (n>avail ? avail : n));
|
||||
}
|
||||
str_l += n;
|
||||
}
|
||||
/* insert zero padding as requested by the precision or min field width */
|
||||
/* insert zero padding as requested by the precision or min field width */
|
||||
n = number_of_zeros_to_pad;
|
||||
if (n > 0) {
|
||||
if (str_l < str_m) {
|
||||
size_t avail = str_m-str_l;
|
||||
fast_memset(str+str_l, '0', (n>avail?avail:n));
|
||||
fast_memset(str+str_l, '0', (n>avail ? avail : n));
|
||||
}
|
||||
str_l += n;
|
||||
}
|
||||
}
|
||||
/* insert formatted string
|
||||
* (or as-is conversion specifier for unknown conversions) */
|
||||
/* insert formatted string
|
||||
* (or as-is conversion specifier for unknown conversions) */
|
||||
{ int n = str_arg_l - zero_padding_insertion_ind;
|
||||
if (n > 0) {
|
||||
if (str_l < str_m) {
|
||||
size_t avail = str_m-str_l;
|
||||
fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
|
||||
(n>avail?avail:n));
|
||||
(n>avail ? avail : n));
|
||||
}
|
||||
str_l += n;
|
||||
}
|
||||
}
|
||||
/* insert right padding */
|
||||
}}
|
||||
/* insert right padding */
|
||||
if (justify_left) { /* right blank padding to the field width */
|
||||
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
|
||||
if (n > 0) {
|
||||
if (str_l < str_m) {
|
||||
size_t avail = str_m-str_l;
|
||||
fast_memset(str+str_l, ' ', (n>avail?avail:n));
|
||||
fast_memset(str+str_l, ' ', (n>avail ? avail : n));
|
||||
}
|
||||
str_l += n;
|
||||
}
|
||||
|
@ -829,7 +822,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
|
|||
#endif
|
||||
#endif /* ndef HAVE_SNPRINTF */
|
||||
/*
|
||||
Local Variables:
|
||||
tab-width: 3
|
||||
end:
|
||||
*/
|
||||
Local Variables:
|
||||
tab-width: 3
|
||||
end:
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/** This module implements AARP, a necessary protocol for ELAP communication. **/
|
||||
|
||||
|
@ -24,10 +24,10 @@
|
|||
|
||||
struct amt_entry_t
|
||||
{
|
||||
struct at_addr_t protocol;
|
||||
struct ether_addr_t hardware;
|
||||
struct at_addr_t protocol;
|
||||
struct ether_addr_t hardware;
|
||||
|
||||
struct amt_entry_t* next;
|
||||
struct amt_entry_t* next;
|
||||
};
|
||||
|
||||
typedef struct amt_entry_t* amt_t;
|
||||
|
@ -38,253 +38,237 @@ static unsigned int retry_count;
|
|||
static clock_t retry_timer;
|
||||
|
||||
|
||||
void aarp_init()
|
||||
{
|
||||
aarp_retry_reset();
|
||||
void aarp_init() {
|
||||
aarp_retry_reset();
|
||||
}
|
||||
|
||||
void aarp_shutdown()
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
while (entry)
|
||||
{
|
||||
struct amt_entry_t* next = entry->next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
}
|
||||
void aarp_shutdown() {
|
||||
struct amt_entry_t* entry = amt;
|
||||
while (entry)
|
||||
{
|
||||
struct amt_entry_t* next = entry->next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
static void aarp_send_packet(enum AARP_FUNCTION function, const struct at_addr_t* source_at_addr, const struct at_addr_t* dest_at_addr, const struct ether_addr_t* dest_hw_addr)
|
||||
{
|
||||
if (source_at_addr && dest_at_addr && dest_hw_addr)
|
||||
{
|
||||
struct aarp_header_t response;
|
||||
response.hardware_type = htons(AARP_HARDWARE_ETHER);
|
||||
response.protocol_type = htons(AARP_PROTOCOL_TYPE);
|
||||
response.hw_addr_len = AARP_HW_ADDR_LEN;
|
||||
response.protocol_addr_len = AARP_PROTOCOL_ADDR_LEN;
|
||||
response.function = htons(function);
|
||||
static void aarp_send_packet(enum AARP_FUNCTION function, const struct at_addr_t* source_at_addr, const struct at_addr_t* dest_at_addr, const struct ether_addr_t* dest_hw_addr) {
|
||||
if (source_at_addr && dest_at_addr && dest_hw_addr)
|
||||
{
|
||||
struct aarp_header_t response;
|
||||
response.hardware_type = htons(AARP_HARDWARE_ETHER);
|
||||
response.protocol_type = htons(AARP_PROTOCOL_TYPE);
|
||||
response.hw_addr_len = AARP_HW_ADDR_LEN;
|
||||
response.protocol_addr_len = AARP_PROTOCOL_ADDR_LEN;
|
||||
response.function = htons(function);
|
||||
|
||||
memcpy(&response.source_proto_addr.addr, source_at_addr, sizeof(response.source_proto_addr.addr));
|
||||
response.source_proto_addr.addr.network = htons(response.source_proto_addr.addr.network);
|
||||
response.source_proto_addr.zero = 0x00;
|
||||
memcpy(&response.source_proto_addr.addr, source_at_addr, sizeof(response.source_proto_addr.addr));
|
||||
response.source_proto_addr.addr.network = htons(response.source_proto_addr.addr.network);
|
||||
response.source_proto_addr.zero = 0x00;
|
||||
|
||||
memcpy(&response.dest_proto_addr.addr, dest_at_addr, sizeof(response.dest_proto_addr.addr));
|
||||
response.dest_proto_addr.addr.network = htons(response.dest_proto_addr.addr.network);
|
||||
response.dest_proto_addr.zero = 0x00;
|
||||
memcpy(&response.dest_proto_addr.addr, dest_at_addr, sizeof(response.dest_proto_addr.addr));
|
||||
response.dest_proto_addr.addr.network = htons(response.dest_proto_addr.addr.network);
|
||||
response.dest_proto_addr.zero = 0x00;
|
||||
|
||||
memcpy(response.source_hw_addr.mac, elap_get_mac()->mac, sizeof(response.source_hw_addr.mac));
|
||||
memcpy(response.source_hw_addr.mac, elap_get_mac()->mac, sizeof(response.source_hw_addr.mac));
|
||||
|
||||
memcpy(response.dest_hw_addr.mac, &dest_hw_addr->mac, sizeof(response.dest_hw_addr.mac));
|
||||
memcpy(response.dest_hw_addr.mac, &dest_hw_addr->mac, sizeof(response.dest_hw_addr.mac));
|
||||
|
||||
if (dest_hw_addr == &HW_ZERO)
|
||||
elap_send(&HW_APPLETALK_BROADCAST, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response);
|
||||
else
|
||||
elap_send(&response.dest_hw_addr, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response);
|
||||
}
|
||||
if (dest_hw_addr == &HW_ZERO)
|
||||
elap_send(&HW_APPLETALK_BROADCAST, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response);
|
||||
else
|
||||
elap_send(&response.dest_hw_addr, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response);
|
||||
}
|
||||
}
|
||||
|
||||
void aarp_probe(const struct at_addr_t* addr)
|
||||
{
|
||||
if (addr)
|
||||
{
|
||||
aarp_send_packet(AARP_FUNCTION_PROBE, addr, addr, &HW_ZERO);
|
||||
}
|
||||
void aarp_probe(const struct at_addr_t* addr) {
|
||||
if (addr)
|
||||
{
|
||||
aarp_send_packet(AARP_FUNCTION_PROBE, addr, addr, &HW_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
static void aarp_request(const struct at_addr_t* addr)
|
||||
{
|
||||
if (addr)
|
||||
{
|
||||
aarp_send_packet(AARP_FUNCTION_REQUEST, atbridge_get_addr(), addr, &HW_ZERO);
|
||||
}
|
||||
static void aarp_request(const struct at_addr_t* addr) {
|
||||
if (addr)
|
||||
{
|
||||
aarp_send_packet(AARP_FUNCTION_REQUEST, atbridge_get_addr(), addr, &HW_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
static struct amt_entry_t* amt_lookup_entry_hardware(const struct ether_addr_t* hardware)
|
||||
{
|
||||
if (hardware)
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
while (entry)
|
||||
{
|
||||
if (memcmp(&entry->hardware, hardware, sizeof(entry->hardware)) == 0)
|
||||
return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
static struct amt_entry_t* amt_lookup_entry_hardware(const struct ether_addr_t* hardware) {
|
||||
if (hardware)
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
while (entry)
|
||||
{
|
||||
if (memcmp(&entry->hardware, hardware, sizeof(entry->hardware)) == 0)
|
||||
return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amt_entry_t* amt_lookup_entry_protocol(const struct at_addr_t* protocol)
|
||||
{
|
||||
if (protocol)
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
while (entry)
|
||||
{
|
||||
if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0)
|
||||
return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
static struct amt_entry_t* amt_lookup_entry_protocol(const struct at_addr_t* protocol) {
|
||||
if (protocol)
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
while (entry)
|
||||
{
|
||||
if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0)
|
||||
return entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amt_delete_entry_protocol(const struct at_addr_t* protocol)
|
||||
{
|
||||
if (protocol)
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
struct amt_entry_t* previous = amt;
|
||||
while (entry)
|
||||
{
|
||||
if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0)
|
||||
{
|
||||
previous->next = entry->next;
|
||||
free(entry);
|
||||
break;
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
static void amt_delete_entry_protocol(const struct at_addr_t* protocol) {
|
||||
if (protocol)
|
||||
{
|
||||
struct amt_entry_t* entry = amt;
|
||||
struct amt_entry_t* previous = amt;
|
||||
while (entry)
|
||||
{
|
||||
if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0)
|
||||
{
|
||||
previous->next = entry->next;
|
||||
free(entry);
|
||||
break;
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void amt_add(const struct at_addr_t* protocol, const struct ether_addr_t* hardware)
|
||||
{
|
||||
// Does an entry matching one of the protocol or hardware addresses exist? If so, update it.
|
||||
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
|
||||
if (entry)
|
||||
{
|
||||
memcpy(&entry->hardware, hardware, sizeof(entry->hardware));
|
||||
return;
|
||||
}
|
||||
static void amt_add(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) {
|
||||
// Does an entry matching one of the protocol or hardware addresses exist? If so, update it.
|
||||
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
|
||||
if (entry)
|
||||
{
|
||||
memcpy(&entry->hardware, hardware, sizeof(entry->hardware));
|
||||
return;
|
||||
}
|
||||
|
||||
entry = amt_lookup_entry_hardware(hardware);
|
||||
if (entry)
|
||||
{
|
||||
memcpy(&entry->protocol, protocol, sizeof(entry->protocol));
|
||||
return;
|
||||
}
|
||||
entry = amt_lookup_entry_hardware(hardware);
|
||||
if (entry)
|
||||
{
|
||||
memcpy(&entry->protocol, protocol, sizeof(entry->protocol));
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, add a new entry.
|
||||
entry = (struct amt_entry_t*)malloc(sizeof(struct amt_entry_t));
|
||||
memcpy(&entry->hardware, hardware, sizeof(entry->hardware));
|
||||
memcpy(&entry->protocol, protocol, sizeof(entry->protocol));
|
||||
entry->next = amt;
|
||||
amt = entry;
|
||||
// Otherwise, add a new entry.
|
||||
entry = (struct amt_entry_t*)malloc(sizeof(struct amt_entry_t));
|
||||
memcpy(&entry->hardware, hardware, sizeof(entry->hardware));
|
||||
memcpy(&entry->protocol, protocol, sizeof(entry->protocol));
|
||||
entry->next = amt;
|
||||
amt = entry;
|
||||
}
|
||||
|
||||
const struct ether_addr_t* aarp_request_hardware(const struct at_addr_t* protocol)
|
||||
{
|
||||
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
|
||||
if (entry)
|
||||
{
|
||||
aarp_retry_reset();
|
||||
return (const struct ether_addr_t*)&entry->hardware;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The AMT doesn't have this protocol address so issue a request at no more than the AARP_PROBE_INTERVAL period.
|
||||
if (((clock() - retry_timer) >= (AARP_REQUEST_INTERVAL * CLOCKS_PER_SEC / 1000)) &&
|
||||
(retry_count > 0))
|
||||
{
|
||||
aarp_request(protocol);
|
||||
|
||||
retry_count--;
|
||||
retry_timer = clock();
|
||||
|
||||
//atbridge_printf("AARP request count %d timer %d.\n", retry_count, retry_timer);
|
||||
}
|
||||
const struct ether_addr_t* aarp_request_hardware(const struct at_addr_t* protocol) {
|
||||
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
|
||||
if (entry)
|
||||
{
|
||||
aarp_retry_reset();
|
||||
return (const struct ether_addr_t*)&entry->hardware;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The AMT doesn't have this protocol address so issue a request at no more than the AARP_PROBE_INTERVAL period.
|
||||
if (((clock() - retry_timer) >= (AARP_REQUEST_INTERVAL * CLOCKS_PER_SEC / 1000)) &&
|
||||
(retry_count > 0))
|
||||
{
|
||||
aarp_request(protocol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
retry_count--;
|
||||
retry_timer = clock();
|
||||
|
||||
//atbridge_printf("AARP request count %d timer %d.\n", retry_count, retry_timer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const struct at_addr_t* aarp_request_protocol(const struct ether_addr_t* hardware)
|
||||
{
|
||||
struct amt_entry_t* entry = amt_lookup_entry_hardware(hardware);
|
||||
if (entry)
|
||||
return (const struct at_addr_t*)&entry->protocol;
|
||||
else
|
||||
return 0;
|
||||
const struct at_addr_t* aarp_request_protocol(const struct ether_addr_t* hardware) {
|
||||
struct amt_entry_t* entry = amt_lookup_entry_hardware(hardware);
|
||||
if (entry)
|
||||
return (const struct at_addr_t*)&entry->protocol;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool aarp_retry()
|
||||
{
|
||||
return retry_count > 0;
|
||||
bool aarp_retry() {
|
||||
return retry_count > 0;
|
||||
}
|
||||
|
||||
void aarp_retry_reset()
|
||||
{
|
||||
retry_count = AARP_REQUEST_COUNT;
|
||||
retry_timer = clock();
|
||||
void aarp_retry_reset() {
|
||||
retry_count = AARP_REQUEST_COUNT;
|
||||
retry_timer = clock();
|
||||
}
|
||||
|
||||
void aarp_glean(const struct at_addr_t* protocol, const struct ether_addr_t* hardware)
|
||||
{
|
||||
amt_add(protocol, hardware);
|
||||
void aarp_glean(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) {
|
||||
amt_add(protocol, hardware);
|
||||
}
|
||||
|
||||
bool aarp_address_used(const struct at_addr_t* protocol)
|
||||
{
|
||||
// reference 2-8
|
||||
if (protocol)
|
||||
{
|
||||
// Check for reserved node numbers, per reference 3-9.
|
||||
if (protocol->node == 0x00 || protocol->node == 0xfe || protocol->node == 0xff)
|
||||
return true;
|
||||
bool aarp_address_used(const struct at_addr_t* protocol) {
|
||||
// reference 2-8
|
||||
if (protocol)
|
||||
{
|
||||
// Check for reserved node numbers, per reference 3-9.
|
||||
if (protocol->node == 0x00 || protocol->node == 0xfe || protocol->node == 0xff)
|
||||
return true;
|
||||
|
||||
// Look for the address in the AMT. If it's there, another node is using this address.
|
||||
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
|
||||
if (entry)
|
||||
return true;
|
||||
// Look for the address in the AMT. If it's there, another node is using this address.
|
||||
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
|
||||
if (entry)
|
||||
return true;
|
||||
|
||||
// Try a probe. If this address is in use, another node will reply with an AARP RESPONSE packet.
|
||||
// Return true to advise the caller that the address is not known to be in use. The caller should
|
||||
// retry aarp_try_address() every 200 ms (AARP_PROBE_INTERVAL) and 10 times (AARP_PROBE_COUNT),
|
||||
// per the AARP protocol definition, before choosing this address.
|
||||
aarp_probe(protocol);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
// Try a probe. If this address is in use, another node will reply with an AARP RESPONSE packet.
|
||||
// Return true to advise the caller that the address is not known to be in use. The caller should
|
||||
// retry aarp_try_address() every 200 ms (AARP_PROBE_INTERVAL) and 10 times (AARP_PROBE_COUNT),
|
||||
// per the AARP protocol definition, before choosing this address.
|
||||
aarp_probe(protocol);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
void aarp_handle_packet(const struct aarp_header_t* aarp)
|
||||
{
|
||||
if (aarp &&
|
||||
aarp->hardware_type == AARP_HARDWARE_ETHER &&
|
||||
aarp->protocol_type == AARP_PROTOCOL_TYPE &&
|
||||
aarp->hw_addr_len == AARP_HW_ADDR_LEN &&
|
||||
aarp->protocol_addr_len == AARP_PROTOCOL_ADDR_LEN)
|
||||
{
|
||||
switch (aarp->function)
|
||||
{
|
||||
case AARP_FUNCTION_REQUEST:
|
||||
if (((aarp->dest_proto_addr.addr.network == atbridge_get_net()) ||
|
||||
(aarp->dest_proto_addr.addr.network == 0x00 /* reference 4-6 */)) &&
|
||||
(aarp->dest_proto_addr.addr.node == atbridge_get_node()))
|
||||
{
|
||||
// Generate a response for the AARP request.
|
||||
aarp_send_packet(AARP_FUNCTION_RESPONSE, &aarp->dest_proto_addr.addr, &aarp->source_proto_addr.addr, &aarp->source_hw_addr);
|
||||
}
|
||||
break;
|
||||
case AARP_FUNCTION_RESPONSE:
|
||||
aarp_glean(&aarp->source_proto_addr.addr, &aarp->source_hw_addr);
|
||||
aarp_glean(&aarp->dest_proto_addr.addr, &aarp->dest_hw_addr);
|
||||
break;
|
||||
case AARP_FUNCTION_PROBE:
|
||||
// AMT entry aging, method 2, reference 2-11
|
||||
amt_delete_entry_protocol(&aarp->dest_proto_addr.addr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void aarp_handle_packet(const struct aarp_header_t* aarp) {
|
||||
if (aarp &&
|
||||
aarp->hardware_type == AARP_HARDWARE_ETHER &&
|
||||
aarp->protocol_type == AARP_PROTOCOL_TYPE &&
|
||||
aarp->hw_addr_len == AARP_HW_ADDR_LEN &&
|
||||
aarp->protocol_addr_len == AARP_PROTOCOL_ADDR_LEN)
|
||||
{
|
||||
switch (aarp->function)
|
||||
{
|
||||
case AARP_FUNCTION_REQUEST:
|
||||
if (((aarp->dest_proto_addr.addr.network == atbridge_get_net()) ||
|
||||
(aarp->dest_proto_addr.addr.network == 0x00 /* reference 4-6 */)) &&
|
||||
(aarp->dest_proto_addr.addr.node == atbridge_get_node()))
|
||||
{
|
||||
// Generate a response for the AARP request.
|
||||
aarp_send_packet(AARP_FUNCTION_RESPONSE, &aarp->dest_proto_addr.addr, &aarp->source_proto_addr.addr, &aarp->source_hw_addr);
|
||||
}
|
||||
break;
|
||||
case AARP_FUNCTION_RESPONSE:
|
||||
aarp_glean(&aarp->source_proto_addr.addr, &aarp->source_hw_addr);
|
||||
aarp_glean(&aarp->dest_proto_addr.addr, &aarp->dest_hw_addr);
|
||||
break;
|
||||
case AARP_FUNCTION_PROBE:
|
||||
// AMT entry aging, method 2, reference 2-11
|
||||
amt_delete_entry_protocol(&aarp->dest_proto_addr.addr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/** This module is the "heart" of the bridge and provides the connection between the ELAP and LLAP ports. **/
|
||||
|
||||
|
@ -37,378 +37,357 @@ static const at_node_t NODE_STARTUP_HIGH = 0xFE;
|
|||
|
||||
static void send_rtmp_request();
|
||||
|
||||
bool atbridge_init()
|
||||
{
|
||||
// If the GS reboots, we may try to reinitialize the bridge. If this is the case, keep the old address and AMT.
|
||||
if (local_address.network == 0)
|
||||
{
|
||||
// Obtain a provisional node address and startup range network.
|
||||
//
|
||||
// This isn't correct for an extended network (like ELAP) but works adequately on small networks.
|
||||
// The bridge should follow the complicated process on page 4-9 to obtain the network and node number.
|
||||
srand((unsigned int)time(0));
|
||||
local_address.network = (at_network_t)((double)rand()/RAND_MAX * (NET_STARTUP_HIGH - NET_STARTUP_LOW) + NET_STARTUP_LOW);
|
||||
local_address.node = (at_node_t)((double)rand()/RAND_MAX + (NODE_STARTUP_HIGH - NODE_STARTUP_LOW) + 0x01);
|
||||
bool atbridge_init() {
|
||||
// If the GS reboots, we may try to reinitialize the bridge. If this is the case, keep the old address and AMT.
|
||||
if (local_address.network == 0)
|
||||
{
|
||||
// Obtain a provisional node address and startup range network.
|
||||
//
|
||||
// This isn't correct for an extended network (like ELAP) but works adequately on small networks.
|
||||
// The bridge should follow the complicated process on page 4-9 to obtain the network and node number.
|
||||
srand((unsigned int)time(0));
|
||||
local_address.network = (at_network_t)((double)rand()/RAND_MAX * (NET_STARTUP_HIGH - NET_STARTUP_LOW) + NET_STARTUP_LOW);
|
||||
local_address.node = (at_node_t)((double)rand()/RAND_MAX + (NODE_STARTUP_HIGH - NODE_STARTUP_LOW) + 0x01);
|
||||
|
||||
aarp_init();
|
||||
llap_init();
|
||||
if (!elap_init())
|
||||
{
|
||||
atbridge_shutdown();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
aarp_init();
|
||||
llap_init();
|
||||
if (!elap_init())
|
||||
{
|
||||
atbridge_shutdown();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void atbridge_shutdown()
|
||||
{
|
||||
llap_shutdown();
|
||||
elap_shutdown();
|
||||
aarp_shutdown();
|
||||
void atbridge_shutdown() {
|
||||
llap_shutdown();
|
||||
elap_shutdown();
|
||||
aarp_shutdown();
|
||||
}
|
||||
|
||||
void atbridge_set_diagnostics(bool enabled)
|
||||
{
|
||||
diagnostics = enabled;
|
||||
void atbridge_set_diagnostics(bool enabled) {
|
||||
diagnostics = enabled;
|
||||
}
|
||||
|
||||
bool atbridge_get_diagnostics()
|
||||
{
|
||||
return diagnostics;
|
||||
bool atbridge_get_diagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
void atbridge_printf(const char *fmt, ...)
|
||||
{
|
||||
if (atbridge_get_diagnostics())
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
void atbridge_printf(const char *fmt, ...) {
|
||||
if (atbridge_get_diagnostics())
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
const struct at_addr_t* atbridge_get_addr()
|
||||
{
|
||||
return &local_address;
|
||||
const struct at_addr_t* atbridge_get_addr() {
|
||||
return &local_address;
|
||||
}
|
||||
|
||||
const at_network_t atbridge_get_net()
|
||||
{
|
||||
return local_address.network;
|
||||
const at_network_t atbridge_get_net() {
|
||||
return local_address.network;
|
||||
}
|
||||
|
||||
const at_node_t atbridge_get_node()
|
||||
{
|
||||
return local_address.node;
|
||||
const at_node_t atbridge_get_node() {
|
||||
return local_address.node;
|
||||
}
|
||||
|
||||
void atbridge_set_net(at_network_t net)
|
||||
{
|
||||
local_address.network = net;
|
||||
void atbridge_set_net(at_network_t net) {
|
||||
local_address.network = net;
|
||||
}
|
||||
|
||||
void atbridge_set_node(at_node_t node)
|
||||
{
|
||||
local_address.node = node;
|
||||
void atbridge_set_node(at_node_t node) {
|
||||
local_address.node = node;
|
||||
}
|
||||
|
||||
bool atbridge_address_used(const struct at_addr_t* addr)
|
||||
{
|
||||
if (!sent_rtmp_request)
|
||||
send_rtmp_request();
|
||||
return aarp_address_used(addr);
|
||||
bool atbridge_address_used(const struct at_addr_t* addr) {
|
||||
if (!sent_rtmp_request)
|
||||
send_rtmp_request();
|
||||
return aarp_address_used(addr);
|
||||
}
|
||||
|
||||
/* Calculate a DDP checksum, per Apple's documented algorithm in 4-17 of "Inside AppleTalk". */
|
||||
static word16 get_checksum(size_t size, byte data[])
|
||||
{
|
||||
word16 cksum = 0;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
cksum += data[i];
|
||||
cksum = (cksum << 1) | ((cksum & 0x8000) >> 15); // roll left
|
||||
}
|
||||
if (cksum == 0)
|
||||
cksum = 0xffff;
|
||||
return cksum;
|
||||
static word16 get_checksum(size_t size, byte data[]) {
|
||||
word16 cksum = 0;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
cksum += data[i];
|
||||
cksum = (cksum << 1) | ((cksum & 0x8000) >> 15); // roll left
|
||||
}
|
||||
if (cksum == 0)
|
||||
cksum = 0xffff;
|
||||
return cksum;
|
||||
}
|
||||
|
||||
static void calculate_checksum(struct packet_t* packet)
|
||||
{
|
||||
if (packet && packet->data && (packet->size >= sizeof(struct DDP_LONG)) && (packet->type == LAP_DDP_LONG))
|
||||
{
|
||||
struct DDP_LONG* header = (struct DDP_LONG*)(packet->data);
|
||||
header->checksum = htons(get_checksum(
|
||||
packet->size - offsetof(struct DDP_LONG, dest_net),
|
||||
(byte*)&header->dest_net));
|
||||
}
|
||||
static void calculate_checksum(struct packet_t* packet) {
|
||||
if (packet && packet->data && (packet->size >= sizeof(struct DDP_LONG)) && (packet->type == LAP_DDP_LONG))
|
||||
{
|
||||
struct DDP_LONG* header = (struct DDP_LONG*)(packet->data);
|
||||
header->checksum = htons(get_checksum(
|
||||
packet->size - offsetof(struct DDP_LONG, dest_net),
|
||||
(byte*)&header->dest_net));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a long-form DDP header to a short-form header. This function only converts the headers. */
|
||||
static word16 convert_ddp_header_to_short(const struct DDP_LONG* in, struct DDP_SHORT* out)
|
||||
{
|
||||
word16 size;
|
||||
static word16 convert_ddp_header_to_short(const struct DDP_LONG* in, struct DDP_SHORT* out) {
|
||||
word16 size;
|
||||
|
||||
if (!in || !out)
|
||||
return 0;
|
||||
|
||||
size = ((in->length[0] & 0x3) << 8) + (in->length[1]) - (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
|
||||
if (!in || !out)
|
||||
return 0;
|
||||
|
||||
out->length[0] = (size >> 8) & 0x03;
|
||||
out->length[1] = size & 0xff;
|
||||
size = ((in->length[0] & 0x3) << 8) + (in->length[1]) - (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
|
||||
|
||||
out->dest_socket = in->dest_socket;
|
||||
out->source_socket = in->source_socket;
|
||||
|
||||
out->type = in->type;
|
||||
out->length[0] = (size >> 8) & 0x03;
|
||||
out->length[1] = size & 0xff;
|
||||
|
||||
return size;
|
||||
out->dest_socket = in->dest_socket;
|
||||
out->source_socket = in->source_socket;
|
||||
|
||||
out->type = in->type;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Convert a short-form DDP header to a long-form header. ELAP requires long-form, but LLAP often uses short-form. */
|
||||
/* This function only converts the headers. */
|
||||
static word16 convert_ddp_header_to_long(const struct at_addr_t dest, const struct at_addr_t source, const struct DDP_SHORT* in, struct DDP_LONG* out)
|
||||
{
|
||||
word16 size;
|
||||
static word16 convert_ddp_header_to_long(const struct at_addr_t dest, const struct at_addr_t source, const struct DDP_SHORT* in, struct DDP_LONG* out) {
|
||||
word16 size;
|
||||
|
||||
if (!in || !out)
|
||||
return 0;
|
||||
|
||||
size = ((in->length[0] & 0x3) << 8) + (in->length[1]) + (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
|
||||
out->length[0] = (size >> 8) & 0x03;
|
||||
out->length[1] = size & 0xff;
|
||||
|
||||
out->checksum = 0x0000; /* 0x0000 == no checksum calculated, reference 4-17 */
|
||||
|
||||
if (dest.network)
|
||||
out->dest_net = dest.network;
|
||||
else
|
||||
out->dest_net = atbridge_get_net();
|
||||
out->dest_net = (at_network_t)htons(out->dest_net);
|
||||
if (!in || !out)
|
||||
return 0;
|
||||
|
||||
if (source.network)
|
||||
out->source_net = source.network;
|
||||
else
|
||||
out->source_net = atbridge_get_net();
|
||||
out->source_net = (at_network_t)htons(out->source_net);
|
||||
size = ((in->length[0] & 0x3) << 8) + (in->length[1]) + (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
|
||||
out->length[0] = (size >> 8) & 0x03;
|
||||
out->length[1] = size & 0xff;
|
||||
|
||||
out->dest_node = dest.node;
|
||||
out->source_node = source.node;
|
||||
out->checksum = 0x0000; /* 0x0000 == no checksum calculated, reference 4-17 */
|
||||
|
||||
out->dest_socket = in->dest_socket;
|
||||
out->source_socket = in->source_socket;
|
||||
if (dest.network)
|
||||
out->dest_net = dest.network;
|
||||
else
|
||||
out->dest_net = atbridge_get_net();
|
||||
out->dest_net = (at_network_t)htons(out->dest_net);
|
||||
|
||||
out->type = in->type;
|
||||
if (source.network)
|
||||
out->source_net = source.network;
|
||||
else
|
||||
out->source_net = atbridge_get_net();
|
||||
out->source_net = (at_network_t)htons(out->source_net);
|
||||
|
||||
return size;
|
||||
out->dest_node = dest.node;
|
||||
out->source_node = source.node;
|
||||
|
||||
out->dest_socket = in->dest_socket;
|
||||
out->source_socket = in->source_socket;
|
||||
|
||||
out->type = in->type;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Convert a short-form DDP packet to a long-form packet. */
|
||||
/* This function converts an entire packet, not just the header. */
|
||||
static void convert_ddp_packet_to_long(struct packet_t* packet)
|
||||
{
|
||||
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data && (packet->size >= sizeof(struct DDP_SHORT)))
|
||||
{
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
|
||||
static void convert_ddp_packet_to_long(struct packet_t* packet) {
|
||||
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data && (packet->size >= sizeof(struct DDP_SHORT)))
|
||||
{
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
|
||||
|
||||
const size_t payload_size = packet->size - sizeof(struct DDP_SHORT);
|
||||
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_LONG));
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)data;
|
||||
const size_t payload_size = packet->size - sizeof(struct DDP_SHORT);
|
||||
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_LONG));
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)data;
|
||||
|
||||
const word16 size = convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long);
|
||||
packet->dest.network = ntohs(header_long->dest_net);
|
||||
packet->source.network = ntohs(header_long->source_net);
|
||||
const word16 size = convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long);
|
||||
packet->dest.network = ntohs(header_long->dest_net);
|
||||
packet->source.network = ntohs(header_long->source_net);
|
||||
|
||||
memcpy(data + sizeof(struct DDP_LONG), packet->data + sizeof(struct DDP_SHORT), payload_size);
|
||||
memcpy(data + sizeof(struct DDP_LONG), packet->data + sizeof(struct DDP_SHORT), payload_size);
|
||||
|
||||
packet->type = LAP_DDP_LONG;
|
||||
packet->size = size;
|
||||
packet->type = LAP_DDP_LONG;
|
||||
packet->size = size;
|
||||
|
||||
// Replace the original short-form packet data.
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
// Replace the original short-form packet data.
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
|
||||
calculate_checksum(packet);
|
||||
}
|
||||
calculate_checksum(packet);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a long-form DDP packet to short-form. */
|
||||
static void convert_ddp_packet_to_short(struct packet_t* packet)
|
||||
{
|
||||
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
|
||||
{
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
|
||||
static void convert_ddp_packet_to_short(struct packet_t* packet) {
|
||||
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
|
||||
{
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
|
||||
|
||||
const size_t payload_size = packet->size - sizeof(struct DDP_LONG);
|
||||
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_SHORT));
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
|
||||
const size_t payload_size = packet->size - sizeof(struct DDP_LONG);
|
||||
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_SHORT));
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
|
||||
|
||||
const word16 size = convert_ddp_header_to_short(header_long, header_short);
|
||||
const word16 size = convert_ddp_header_to_short(header_long, header_short);
|
||||
|
||||
memcpy(data + sizeof(struct DDP_SHORT), packet->data + sizeof(struct DDP_LONG), payload_size);
|
||||
memcpy(data + sizeof(struct DDP_SHORT), packet->data + sizeof(struct DDP_LONG), payload_size);
|
||||
|
||||
packet->type = LAP_DDP_SHORT;
|
||||
packet->size = size;
|
||||
packet->type = LAP_DDP_SHORT;
|
||||
packet->size = size;
|
||||
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
}
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
}
|
||||
}
|
||||
|
||||
/*static void convert_rtmp_to_extended(struct packet_t* packet)
|
||||
{
|
||||
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data)
|
||||
{
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
|
||||
if (header_short->type != DDP_TYPE_RTMP || header_short->dest_socket != DDP_SOCKET_RTMP)
|
||||
return;
|
||||
{
|
||||
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data)
|
||||
{
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
|
||||
if (header_short->type != DDP_TYPE_RTMP || header_short->dest_socket != DDP_SOCKET_RTMP)
|
||||
return;
|
||||
|
||||
struct rtmp_nonextended_data_t* in = (struct rtmp_nonextended_data_t*)(packet->data + sizeof(struct DDP_SHORT));
|
||||
struct rtmp_nonextended_data_t* in = (struct rtmp_nonextended_data_t*)(packet->data + sizeof(struct DDP_SHORT));
|
||||
|
||||
// Construct a new long-form DDP packet header.
|
||||
size_t size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_extended_data_t);
|
||||
byte* data = (byte*)malloc(size);
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)data;
|
||||
convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long);
|
||||
|
||||
struct rtmp_extended_data_t* out = (struct rtmp_extended_data_t*)(data + sizeof(struct DDP_LONG));
|
||||
out->net = in->net;
|
||||
out->id_length = in->id_length;
|
||||
out->node = in->node;
|
||||
// Construct a new long-form DDP packet header.
|
||||
size_t size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_extended_data_t);
|
||||
byte* data = (byte*)malloc(size);
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)data;
|
||||
convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long);
|
||||
|
||||
// Copy the routing tuples.
|
||||
struct rtmp_nonextended_tuple_t* in_tuple = (struct rtmp_nonextended_tuple_t*)(packet->data + sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_data_t));
|
||||
struct rtmp_extended_tuple_t* out_tuple = (struct rtmp_extended_tuple_t*)(data + size);
|
||||
while ((byte*)in_tuple < (packet->data + packet->size))
|
||||
{
|
||||
size += sizeof(struct rtmp_extended_tuple_t);
|
||||
realloc(data, size);
|
||||
out_tuple->range_start = in_tuple->net;
|
||||
out_tuple->distance = in_tuple->distance | 0x80;
|
||||
out_tuple->range_end = in_tuple->net;
|
||||
out_tuple->delimiter = RTMP_TUPLE_DELIMITER;
|
||||
in_tuple++;
|
||||
}
|
||||
struct rtmp_extended_data_t* out = (struct rtmp_extended_data_t*)(data + sizeof(struct DDP_LONG));
|
||||
out->net = in->net;
|
||||
out->id_length = in->id_length;
|
||||
out->node = in->node;
|
||||
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
packet->size = size;
|
||||
packet->type = LAP_DDP_LONG;
|
||||
}
|
||||
}*/
|
||||
// Copy the routing tuples.
|
||||
struct rtmp_nonextended_tuple_t* in_tuple = (struct rtmp_nonextended_tuple_t*)(packet->data + sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_data_t));
|
||||
struct rtmp_extended_tuple_t* out_tuple = (struct rtmp_extended_tuple_t*)(data + size);
|
||||
while ((byte*)in_tuple < (packet->data + packet->size))
|
||||
{
|
||||
size += sizeof(struct rtmp_extended_tuple_t);
|
||||
realloc(data, size);
|
||||
out_tuple->range_start = in_tuple->net;
|
||||
out_tuple->distance = in_tuple->distance | 0x80;
|
||||
out_tuple->range_end = in_tuple->net;
|
||||
out_tuple->delimiter = RTMP_TUPLE_DELIMITER;
|
||||
in_tuple++;
|
||||
}
|
||||
|
||||
static void convert_rtmp_to_nonextended(struct packet_t* packet)
|
||||
{
|
||||
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
|
||||
{
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
|
||||
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP)
|
||||
return;
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
packet->size = size;
|
||||
packet->type = LAP_DDP_LONG;
|
||||
}
|
||||
}*/
|
||||
|
||||
struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
|
||||
static void convert_rtmp_to_nonextended(struct packet_t* packet) {
|
||||
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
|
||||
{
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
|
||||
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP)
|
||||
return;
|
||||
|
||||
size_t size = sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_response_t);
|
||||
byte* data = (byte*)malloc(size);
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
|
||||
convert_ddp_header_to_short(header_long, header_short);
|
||||
header_short->length[0] = (size >> 8) & 0x03;
|
||||
header_short->length[1] = size & 0xff;
|
||||
struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
|
||||
|
||||
struct rtmp_nonextended_response_t* out = (struct rtmp_nonextended_response_t*)(data + sizeof(struct DDP_SHORT));
|
||||
out->net = in->net;
|
||||
out->id_length = in->id_length;
|
||||
out->node = in->node;
|
||||
size_t size = sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_response_t);
|
||||
byte* data = (byte*)malloc(size);
|
||||
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
|
||||
convert_ddp_header_to_short(header_long, header_short);
|
||||
header_short->length[0] = (size >> 8) & 0x03;
|
||||
header_short->length[1] = size & 0xff;
|
||||
|
||||
/*rtmp_extended_tuple_t* in_tuple = (rtmp_extended_tuple_t*)(packet->data + sizeof(DDP_LONG) + sizeof(rtmp_extended_data_t));
|
||||
rtmp_nonextended_tuple_t* out_tuple = (rtmp_nonextended_tuple_t*)(data + size);
|
||||
while ((byte*)in_tuple < (packet->data + packet->size))
|
||||
{
|
||||
size += sizeof(rtmp_nonextended_tuple_t);
|
||||
realloc(data, size);
|
||||
out_tuple->net = in_tuple->range_start;
|
||||
out_tuple->distance = in_tuple->distance & 0x7f;
|
||||
in_tuple++;
|
||||
}*/
|
||||
struct rtmp_nonextended_response_t* out = (struct rtmp_nonextended_response_t*)(data + sizeof(struct DDP_SHORT));
|
||||
out->net = in->net;
|
||||
out->id_length = in->id_length;
|
||||
out->node = in->node;
|
||||
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
packet->size = size;
|
||||
packet->type = LAP_DDP_SHORT;
|
||||
}
|
||||
/*rtmp_extended_tuple_t* in_tuple = (rtmp_extended_tuple_t*)(packet->data + sizeof(DDP_LONG) + sizeof(rtmp_extended_data_t));
|
||||
rtmp_nonextended_tuple_t* out_tuple = (rtmp_nonextended_tuple_t*)(data + size);
|
||||
while ((byte*)in_tuple < (packet->data + packet->size))
|
||||
{
|
||||
size += sizeof(rtmp_nonextended_tuple_t);
|
||||
realloc(data, size);
|
||||
out_tuple->net = in_tuple->range_start;
|
||||
out_tuple->distance = in_tuple->distance & 0x7f;
|
||||
in_tuple++;
|
||||
}*/
|
||||
|
||||
free(packet->data);
|
||||
packet->data = data;
|
||||
packet->size = size;
|
||||
packet->type = LAP_DDP_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Learn our network number from RTMP packets. */
|
||||
/* "Inside AppleTalk", section 4-8, describes this approach for non-extended networks.
|
||||
Technically, we probably should be doing the more complicated extended network approach (also on 4-8),
|
||||
but the easy approach using RTMP seems adequate for now. */
|
||||
static void glean_net_from_rtmp(struct packet_t* packet)
|
||||
{
|
||||
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
|
||||
{
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
|
||||
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP)
|
||||
return;
|
||||
static void glean_net_from_rtmp(struct packet_t* packet) {
|
||||
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
|
||||
{
|
||||
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
|
||||
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP)
|
||||
return;
|
||||
|
||||
struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
|
||||
struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
|
||||
|
||||
atbridge_set_net(ntohs(in->net));
|
||||
}
|
||||
atbridge_set_net(ntohs(in->net));
|
||||
}
|
||||
}
|
||||
|
||||
static void send_rtmp_request()
|
||||
{
|
||||
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
|
||||
packet->type = LAP_DDP_LONG;
|
||||
packet->dest.network = atbridge_get_net();
|
||||
packet->dest.node = 255;
|
||||
packet->source.network = atbridge_get_net();
|
||||
packet->source.node = atbridge_get_node();
|
||||
packet->next = 0;
|
||||
packet->size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_request_t);
|
||||
packet->data = (byte*)malloc(packet->size);
|
||||
static void send_rtmp_request() {
|
||||
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
|
||||
struct DDP_LONG* header = (struct DDP_LONG*)packet->data;
|
||||
header->type = DDP_TYPE_RTMP_REQUEST;
|
||||
header->source_net = htons(packet->source.network);
|
||||
header->source_node = packet->source.node;
|
||||
header->source_socket = DDP_SOCKET_RTMP;
|
||||
header->dest_net = htons(packet->dest.network);
|
||||
header->dest_node = packet->dest.node;
|
||||
header->dest_socket = DDP_SOCKET_RTMP;
|
||||
header->length[0] = (packet->size >> 8) & 0x03;
|
||||
header->length[1] = packet->size & 0xff;
|
||||
packet->type = LAP_DDP_LONG;
|
||||
packet->dest.network = atbridge_get_net();
|
||||
packet->dest.node = 255;
|
||||
packet->source.network = atbridge_get_net();
|
||||
packet->source.node = atbridge_get_node();
|
||||
packet->next = 0;
|
||||
packet->size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_request_t);
|
||||
packet->data = (byte*)malloc(packet->size);
|
||||
|
||||
struct rtmp_request_t* request = (struct rtmp_request_t*)(packet->data + sizeof(struct DDP_LONG));
|
||||
request->function = RTMP_FUNCTION_REQUEST;
|
||||
struct DDP_LONG* header = (struct DDP_LONG*)packet->data;
|
||||
header->type = DDP_TYPE_RTMP_REQUEST;
|
||||
header->source_net = htons(packet->source.network);
|
||||
header->source_node = packet->source.node;
|
||||
header->source_socket = DDP_SOCKET_RTMP;
|
||||
header->dest_net = htons(packet->dest.network);
|
||||
header->dest_node = packet->dest.node;
|
||||
header->dest_socket = DDP_SOCKET_RTMP;
|
||||
header->length[0] = (packet->size >> 8) & 0x03;
|
||||
header->length[1] = packet->size & 0xff;
|
||||
|
||||
calculate_checksum(packet);
|
||||
|
||||
elap_enqueue_out(packet);
|
||||
sent_rtmp_request = true;
|
||||
struct rtmp_request_t* request = (struct rtmp_request_t*)(packet->data + sizeof(struct DDP_LONG));
|
||||
request->function = RTMP_FUNCTION_REQUEST;
|
||||
|
||||
calculate_checksum(packet);
|
||||
|
||||
elap_enqueue_out(packet);
|
||||
sent_rtmp_request = true;
|
||||
}
|
||||
|
||||
void atbridge_process()
|
||||
{
|
||||
elap_process();
|
||||
//llap_process();
|
||||
|
||||
struct packet_t* packet = elap_dequeue_in();
|
||||
if (packet)
|
||||
{
|
||||
glean_net_from_rtmp(packet);
|
||||
convert_rtmp_to_nonextended(packet);
|
||||
// The GS should understand long-form DDP, but converting to short-form ought to slightly improve performance (fewer bytes for the GS to process).
|
||||
convert_ddp_packet_to_short(packet);
|
||||
llap_enqueue_out(packet);
|
||||
}
|
||||
packet = llap_dequeue_in();
|
||||
if (packet)
|
||||
{
|
||||
// ELAP does not support short-form DDP, so convert such packets to long-form.
|
||||
convert_ddp_packet_to_long(packet);
|
||||
elap_enqueue_out(packet);
|
||||
}
|
||||
void atbridge_process() {
|
||||
elap_process();
|
||||
//llap_process();
|
||||
|
||||
struct packet_t* packet = elap_dequeue_in();
|
||||
if (packet)
|
||||
{
|
||||
glean_net_from_rtmp(packet);
|
||||
convert_rtmp_to_nonextended(packet);
|
||||
// The GS should understand long-form DDP, but converting to short-form ought to slightly improve performance (fewer bytes for the GS to process).
|
||||
convert_ddp_packet_to_short(packet);
|
||||
llap_enqueue_out(packet);
|
||||
}
|
||||
packet = llap_dequeue_in();
|
||||
if (packet)
|
||||
{
|
||||
// ELAP does not support short-form DDP, so convert such packets to long-form.
|
||||
convert_ddp_packet_to_long(packet);
|
||||
elap_enqueue_out(packet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/** This module implements the ELAP port of the bridge. **/
|
||||
|
||||
|
@ -37,350 +37,338 @@ static struct packet_port_t elap_port;
|
|||
static struct ether_addr_t HW_LOCAL;
|
||||
|
||||
/*static void dump_device_list(pcap_if_t* devices)
|
||||
{
|
||||
int i = 0;
|
||||
for(pcap_if_t* device = devices; device; device = device->next)
|
||||
{
|
||||
printf("%d. %s", ++i, device->name);
|
||||
if (device->description)
|
||||
printf(" (%s)\n", device->description);
|
||||
else
|
||||
printf(" (No description available)\n");
|
||||
}
|
||||
}*/
|
||||
{
|
||||
int i = 0;
|
||||
for(pcap_if_t* device = devices; device; device = device->next)
|
||||
{
|
||||
printf("%d. %s", ++i, device->name);
|
||||
if (device->description)
|
||||
printf(" (%s)\n", device->description);
|
||||
else
|
||||
printf(" (No description available)\n");
|
||||
}
|
||||
}*/
|
||||
|
||||
static void elap_clone_host_mac(pcap_if_t* device)
|
||||
{
|
||||
if (!device)
|
||||
return;
|
||||
static void elap_clone_host_mac(pcap_if_t* device) {
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
#ifdef WIN32
|
||||
////
|
||||
// Extract the device GUID, which Windows uses to identify the device.
|
||||
char* name = device->name;
|
||||
while (name && *name != '{')
|
||||
name++;
|
||||
size_t guidLen = strlen(name);
|
||||
////
|
||||
// Extract the device GUID, which Windows uses to identify the device.
|
||||
char* name = device->name;
|
||||
while (name && *name != '{')
|
||||
name++;
|
||||
size_t guidLen = strlen(name);
|
||||
|
||||
////
|
||||
// Find and copy the device MAC address.
|
||||
ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 15;
|
||||
IP_ADAPTER_ADDRESSES* addresses = malloc(size);
|
||||
|
||||
ULONG result = GetAdaptersAddresses(AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
|
||||
|
||||
if (result == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
// The addresses buffer is too small. Allocate a bigger buffer.
|
||||
free(addresses);
|
||||
addresses = malloc(size);
|
||||
result = GetAdaptersAddresses(AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
|
||||
}
|
||||
////
|
||||
// Find and copy the device MAC address.
|
||||
ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 15;
|
||||
IP_ADAPTER_ADDRESSES* addresses = malloc(size);
|
||||
|
||||
if (result == NO_ERROR)
|
||||
{
|
||||
// Search for the desired adapter address.
|
||||
IP_ADAPTER_ADDRESSES* current = addresses;
|
||||
while (current)
|
||||
{
|
||||
if (current->PhysicalAddressLength == ETHER_ADDR_LEN && memcmp(current->AdapterName, name, guidLen) == 0)
|
||||
{
|
||||
memcpy(&HW_LOCAL.mac, ¤t->PhysicalAddress, sizeof(HW_LOCAL.mac));
|
||||
break;
|
||||
}
|
||||
current = current->Next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
halt_printf("ATBridge: Failed to find host MAC address (%d).", result);
|
||||
}
|
||||
ULONG result = GetAdaptersAddresses(AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
|
||||
|
||||
free(addresses);
|
||||
if (result == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
// The addresses buffer is too small. Allocate a bigger buffer.
|
||||
free(addresses);
|
||||
addresses = malloc(size);
|
||||
result = GetAdaptersAddresses(AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
|
||||
}
|
||||
|
||||
if (result == NO_ERROR)
|
||||
{
|
||||
// Search for the desired adapter address.
|
||||
IP_ADAPTER_ADDRESSES* current = addresses;
|
||||
while (current)
|
||||
{
|
||||
if (current->PhysicalAddressLength == ETHER_ADDR_LEN && memcmp(current->AdapterName, name, guidLen) == 0)
|
||||
{
|
||||
memcpy(&HW_LOCAL.mac, ¤t->PhysicalAddress, sizeof(HW_LOCAL.mac));
|
||||
break;
|
||||
}
|
||||
current = current->Next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
halt_printf("ATBridge: Failed to find host MAC address (%d).", result);
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
#else
|
||||
#ifdef AF_PACKET
|
||||
struct pcap_addr* address;
|
||||
for (address = device->addresses; address != 0; address = address->next)
|
||||
if (address->addr->sa_family == AF_PACKET)
|
||||
{
|
||||
struct sockaddr_ll* ll = (struct sockaddr_ll*)address->addr;
|
||||
memcpy(&HW_LOCAL.mac, ll->sll_addr, sizeof(HW_LOCAL.mac));
|
||||
}
|
||||
struct pcap_addr* address;
|
||||
for (address = device->addresses; address != 0; address = address->next)
|
||||
if (address->addr->sa_family == AF_PACKET)
|
||||
{
|
||||
struct sockaddr_ll* ll = (struct sockaddr_ll*)address->addr;
|
||||
memcpy(&HW_LOCAL.mac, ll->sll_addr, sizeof(HW_LOCAL.mac));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
const struct ether_addr_t* elap_get_mac()
|
||||
{
|
||||
return &HW_LOCAL;
|
||||
const struct ether_addr_t* elap_get_mac() {
|
||||
return &HW_LOCAL;
|
||||
}
|
||||
|
||||
bool elap_init()
|
||||
{
|
||||
port_init(&elap_port);
|
||||
bool elap_init() {
|
||||
port_init(&elap_port);
|
||||
|
||||
memcpy(&HW_LOCAL, &HW_LOCAL_DEFAULT, sizeof(HW_LOCAL));
|
||||
memcpy(&HW_LOCAL, &HW_LOCAL_DEFAULT, sizeof(HW_LOCAL));
|
||||
|
||||
pcap_if_t* device;
|
||||
pcap_if_t* alldevs;
|
||||
int i = 0;
|
||||
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
// Load the PCAP library.
|
||||
if (!pcapdelay_load())
|
||||
{
|
||||
halt_printf("ATBridge: PCAP not available.\n");
|
||||
return false;
|
||||
}
|
||||
pcap_if_t* device;
|
||||
pcap_if_t* alldevs;
|
||||
int i = 0;
|
||||
|
||||
// Retrieve the device list.
|
||||
if(pcapdelay_findalldevs(&alldevs, errbuf) == -1)
|
||||
{
|
||||
atbridge_printf("ATBridge: Error enumerating PCAP devices: %s\n", errbuf);
|
||||
return false;
|
||||
}
|
||||
//dump_device_list(alldevs);
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
// Jump to the selected adapter.
|
||||
for (device = alldevs, i = 0; i < g_ethernet_interface; device = device->next, i++);
|
||||
if (!device)
|
||||
{
|
||||
halt_printf("ATBridge: PCAP device not found. Check interface number in settings.\n");
|
||||
return false;
|
||||
}
|
||||
// Load the PCAP library.
|
||||
if (!pcapdelay_load())
|
||||
{
|
||||
halt_printf("ATBridge: PCAP not available.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clone the MAC address of the underlying interface. In certain configurations (e.g. Windows with an MS Loopback
|
||||
// interface), the interface, even in promiscous mode, filters foreign MAC addresses.
|
||||
elap_clone_host_mac(device);
|
||||
// Retrieve the device list.
|
||||
if(pcapdelay_findalldevs(&alldevs, errbuf) == -1)
|
||||
{
|
||||
atbridge_printf("ATBridge: Error enumerating PCAP devices: %s\n", errbuf);
|
||||
return false;
|
||||
}
|
||||
//dump_device_list(alldevs);
|
||||
|
||||
// Open the adapter,
|
||||
if ((pcap_session = pcapdelay_open_live(device->name, // name of the device
|
||||
65536, // portion of the packet to capture.
|
||||
// 65536 grants that the whole packet will be captured on all the MACs.
|
||||
1, // promiscuous mode (nonzero means promiscuous)
|
||||
1, // read timeout
|
||||
errbuf // error buffer
|
||||
)) == NULL)
|
||||
{
|
||||
halt_printf("ATBridge: Unable to open the adapter. Pcap does not support %s.\n", device->name);
|
||||
pcapdelay_freealldevs(alldevs);
|
||||
return false;
|
||||
}
|
||||
// Jump to the selected adapter.
|
||||
for (device = alldevs, i = 0; i < g_ethernet_interface; device = device->next, i++);
|
||||
if (!device)
|
||||
{
|
||||
halt_printf("ATBridge: PCAP device not found. Check interface number in settings.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The device must support Ethernet because the bridge "speaks" EtherTalk.
|
||||
if (pcapdelay_datalink(pcap_session) == DLT_EN10MB)
|
||||
{
|
||||
pcapdelay_setnonblock(pcap_session, 1, errbuf);
|
||||
// Clone the MAC address of the underlying interface. In certain configurations (e.g. Windows with an MS Loopback
|
||||
// interface), the interface, even in promiscous mode, filters foreign MAC addresses.
|
||||
elap_clone_host_mac(device);
|
||||
|
||||
atbridge_printf("ATBridge: AppleTalk bridging using network device '%s' with Ethernet address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X.\n",
|
||||
device->description, HW_LOCAL.mac[0], HW_LOCAL.mac[1], HW_LOCAL.mac[2], HW_LOCAL.mac[3], HW_LOCAL.mac[4], HW_LOCAL.mac[5]);
|
||||
|
||||
pcapdelay_freealldevs(alldevs);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcapdelay_close(pcap_session);
|
||||
pcap_session = 0;
|
||||
halt_printf("ATBridge: Selected network device %s must support Ethernet.\n", device->description);
|
||||
pcapdelay_freealldevs(alldevs);
|
||||
return false;
|
||||
}
|
||||
// Open the adapter,
|
||||
if ((pcap_session = pcapdelay_open_live(device->name, // name of the device
|
||||
65536, // portion of the packet to capture.
|
||||
// 65536 grants that the whole packet will be captured on all the MACs.
|
||||
1, // promiscuous mode (nonzero means promiscuous)
|
||||
1, // read timeout
|
||||
errbuf // error buffer
|
||||
)) == NULL)
|
||||
{
|
||||
halt_printf("ATBridge: Unable to open the adapter. Pcap does not support %s.\n", device->name);
|
||||
pcapdelay_freealldevs(alldevs);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The device must support Ethernet because the bridge "speaks" EtherTalk.
|
||||
if (pcapdelay_datalink(pcap_session) == DLT_EN10MB)
|
||||
{
|
||||
pcapdelay_setnonblock(pcap_session, 1, errbuf);
|
||||
|
||||
atbridge_printf("ATBridge: AppleTalk bridging using network device '%s' with Ethernet address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X.\n",
|
||||
device->description, HW_LOCAL.mac[0], HW_LOCAL.mac[1], HW_LOCAL.mac[2], HW_LOCAL.mac[3], HW_LOCAL.mac[4], HW_LOCAL.mac[5]);
|
||||
|
||||
pcapdelay_freealldevs(alldevs);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcapdelay_close(pcap_session);
|
||||
pcap_session = 0;
|
||||
halt_printf("ATBridge: Selected network device %s must support Ethernet.\n", device->description);
|
||||
pcapdelay_freealldevs(alldevs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void elap_shutdown()
|
||||
{
|
||||
port_shutdown(&elap_port);
|
||||
if (pcap_session)
|
||||
{
|
||||
pcapdelay_close(pcap_session);
|
||||
pcap_session = 0;
|
||||
}
|
||||
pcapdelay_unload();
|
||||
void elap_shutdown() {
|
||||
port_shutdown(&elap_port);
|
||||
if (pcap_session)
|
||||
{
|
||||
pcapdelay_close(pcap_session);
|
||||
pcap_session = 0;
|
||||
}
|
||||
pcapdelay_unload();
|
||||
}
|
||||
|
||||
void elap_enqueue_out(struct packet_t* packet)
|
||||
{
|
||||
enqueue_packet(&elap_port.out, packet);
|
||||
void elap_enqueue_out(struct packet_t* packet) {
|
||||
enqueue_packet(&elap_port.out, packet);
|
||||
}
|
||||
|
||||
struct packet_t* elap_dequeue_in()
|
||||
{
|
||||
return dequeue(&elap_port.in);
|
||||
struct packet_t* elap_dequeue_in() {
|
||||
return dequeue(&elap_port.in);
|
||||
}
|
||||
|
||||
void elap_send(const struct ether_addr_t* dest, const struct snap_discriminator_t* discriminator, size_t size, byte data[])
|
||||
{
|
||||
if (pcap_session && dest && discriminator)
|
||||
{
|
||||
// Allocate heap space for the frame.
|
||||
const size_t frame_size = sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t) + size;
|
||||
u_char* frame_data;
|
||||
size_t pad = 0;
|
||||
if (frame_size < ETHER_MIN_SIZE)
|
||||
pad = ETHER_MIN_SIZE - frame_size;
|
||||
frame_data = (u_char*)malloc(frame_size + pad);
|
||||
void elap_send(const struct ether_addr_t* dest, const struct snap_discriminator_t* discriminator, size_t size, byte data[]) {
|
||||
if (pcap_session && dest && discriminator)
|
||||
{
|
||||
// Allocate heap space for the frame.
|
||||
const size_t frame_size = sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t) + size;
|
||||
u_char* frame_data;
|
||||
size_t pad = 0;
|
||||
if (frame_size < ETHER_MIN_SIZE)
|
||||
pad = ETHER_MIN_SIZE - frame_size;
|
||||
frame_data = (u_char*)malloc(frame_size + pad);
|
||||
|
||||
// Build the 802.3 header.
|
||||
struct ethernet_header_t* ether = (struct ethernet_header_t*)frame_data;
|
||||
memcpy(ether->dest.mac, dest, sizeof(ether->dest.mac));
|
||||
memcpy(ether->source.mac, HW_LOCAL.mac, sizeof(ether->source.mac));
|
||||
ether->length = htons(frame_size - sizeof(struct ethernet_header_t));
|
||||
// Build the 802.3 header.
|
||||
struct ethernet_header_t* ether = (struct ethernet_header_t*)frame_data;
|
||||
memcpy(ether->dest.mac, dest, sizeof(ether->dest.mac));
|
||||
memcpy(ether->source.mac, HW_LOCAL.mac, sizeof(ether->source.mac));
|
||||
ether->length = htons(frame_size - sizeof(struct ethernet_header_t));
|
||||
|
||||
// Build the 802.2 header.
|
||||
struct snap_header_t* snap = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t));
|
||||
snap->dsap = SNAP_DSAP;
|
||||
snap->ssap = SNAP_SSAP;
|
||||
snap->control = SNAP_CONTROL;
|
||||
memcpy(&snap->discriminator, discriminator, sizeof(snap->discriminator));
|
||||
// Build the 802.2 header.
|
||||
struct snap_header_t* snap = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t));
|
||||
snap->dsap = SNAP_DSAP;
|
||||
snap->ssap = SNAP_SSAP;
|
||||
snap->control = SNAP_CONTROL;
|
||||
memcpy(&snap->discriminator, discriminator, sizeof(snap->discriminator));
|
||||
|
||||
// Add the data payload.
|
||||
struct snap_header_t* payload = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t));
|
||||
memcpy(payload, data, size);
|
||||
// Add the data payload.
|
||||
struct snap_header_t* payload = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t));
|
||||
memcpy(payload, data, size);
|
||||
|
||||
// Add padding to meet minimum Ethernet frame size.
|
||||
if (pad > 0)
|
||||
memset(frame_data + frame_size, 0, pad);
|
||||
// Add padding to meet minimum Ethernet frame size.
|
||||
if (pad > 0)
|
||||
memset(frame_data + frame_size, 0, pad);
|
||||
|
||||
pcapdelay_sendpacket(pcap_session, frame_data, frame_size + pad);
|
||||
}
|
||||
pcapdelay_sendpacket(pcap_session, frame_data, frame_size + pad);
|
||||
}
|
||||
}
|
||||
|
||||
static bool elap_send_one_queued()
|
||||
{
|
||||
// Attempt to send one packet out the host network interface.
|
||||
struct packet_t* packet = queue_peek(&elap_port.out);
|
||||
if (packet)
|
||||
{
|
||||
// Find the MAC address.
|
||||
const struct ether_addr_t* dest;
|
||||
if (packet->dest.node == at_broadcast_node)
|
||||
dest = &HW_APPLETALK_BROADCAST;
|
||||
else
|
||||
dest = aarp_request_hardware(&packet->dest);
|
||||
static bool elap_send_one_queued() {
|
||||
// Attempt to send one packet out the host network interface.
|
||||
struct packet_t* packet = queue_peek(&elap_port.out);
|
||||
if (packet)
|
||||
{
|
||||
// Find the MAC address.
|
||||
const struct ether_addr_t* dest;
|
||||
if (packet->dest.node == at_broadcast_node)
|
||||
dest = &HW_APPLETALK_BROADCAST;
|
||||
else
|
||||
dest = aarp_request_hardware(&packet->dest);
|
||||
|
||||
// Send it.
|
||||
if (dest)
|
||||
{
|
||||
elap_send(dest, &SNAP_APPLETALK, packet->size, packet->data);
|
||||
// Send it.
|
||||
if (dest)
|
||||
{
|
||||
elap_send(dest, &SNAP_APPLETALK, packet->size, packet->data);
|
||||
|
||||
dequeue(&elap_port.out);
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
// AARP does not have the needed hardware address. Give AARP time to obtain the address and keep the current packet.
|
||||
if (!aarp_retry())
|
||||
{
|
||||
// However, if AARP has reached the retry limit, the packet is undeliverable. Discard the packet and move on.
|
||||
atbridge_printf("ATBridge: AARP failed to find MAC address for network %d node %d. Dropping packet.\n", packet->dest.network, packet->dest.node);
|
||||
aarp_retry_reset();
|
||||
dequeue(&elap_port.out);
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
dequeue(&elap_port.out);
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
// AARP does not have the needed hardware address. Give AARP time to obtain the address and keep the current packet.
|
||||
if (!aarp_retry())
|
||||
{
|
||||
// However, if AARP has reached the retry limit, the packet is undeliverable. Discard the packet and move on.
|
||||
atbridge_printf("ATBridge: AARP failed to find MAC address for network %d node %d. Dropping packet.\n", packet->dest.network, packet->dest.node);
|
||||
aarp_retry_reset();
|
||||
dequeue(&elap_port.out);
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void elap_send_all_queued()
|
||||
{
|
||||
while (elap_send_one_queued());
|
||||
static void elap_send_all_queued() {
|
||||
while (elap_send_one_queued());
|
||||
}
|
||||
|
||||
static bool elap_receive_one()
|
||||
{
|
||||
if (!pcap_session)
|
||||
return false;
|
||||
static bool elap_receive_one() {
|
||||
if (!pcap_session)
|
||||
return false;
|
||||
|
||||
struct pcap_pkthdr header;
|
||||
const u_char* packet = pcapdelay_next(pcap_session, &header);
|
||||
if (packet)
|
||||
{
|
||||
// Receive and process one packet from the host network interface.
|
||||
////
|
||||
struct pcap_pkthdr header;
|
||||
const u_char* packet = pcapdelay_next(pcap_session, &header);
|
||||
if (packet)
|
||||
{
|
||||
// Receive and process one packet from the host network interface.
|
||||
////
|
||||
|
||||
// Check the Ethernet 802.3 header.
|
||||
const struct ethernet_header_t* ether = (struct ethernet_header_t*)packet;
|
||||
if (header.len > sizeof(struct ethernet_header_t) &&
|
||||
ntohs(ether->length) <= ETHER_MAX_SIZE &&
|
||||
ntohs(ether->length) > sizeof(struct snap_header_t) &&
|
||||
(memcmp(ðer->source, &HW_LOCAL, sizeof(ether->source)) != 0) && /* Ignore packets sent from our node. */
|
||||
(memcmp(ðer->dest, &HW_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
|
||||
memcmp(ðer->dest, &HW_APPLETALK_BROADCAST, sizeof(ether->dest)) == 0 /* ... or for broadcast. */)
|
||||
)
|
||||
{
|
||||
// Check the 802.2 SNAP header.
|
||||
const struct snap_header_t* snap = (struct snap_header_t*)(packet + sizeof(struct ethernet_header_t));
|
||||
if (snap->dsap == SNAP_DSAP &&
|
||||
snap->ssap == SNAP_SSAP &&
|
||||
snap->control == SNAP_CONTROL)
|
||||
{
|
||||
if (memcmp(&snap->discriminator, &SNAP_APPLETALK, sizeof(snap->discriminator)) == 0)
|
||||
{
|
||||
// Handle an AppleTalk packet.
|
||||
const size_t payload_size = ntohs(ether->length) - sizeof(struct snap_header_t);
|
||||
const u_char* payload = packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t);
|
||||
// Check the Ethernet 802.3 header.
|
||||
const struct ethernet_header_t* ether = (struct ethernet_header_t*)packet;
|
||||
if (header.len > sizeof(struct ethernet_header_t) &&
|
||||
ntohs(ether->length) <= ETHER_MAX_SIZE &&
|
||||
ntohs(ether->length) > sizeof(struct snap_header_t) &&
|
||||
(memcmp(ðer->source, &HW_LOCAL, sizeof(ether->source)) != 0) && /* Ignore packets sent from our node. */
|
||||
(memcmp(ðer->dest, &HW_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
|
||||
memcmp(ðer->dest, &HW_APPLETALK_BROADCAST, sizeof(ether->dest)) == 0 /* ... or for broadcast. */)
|
||||
)
|
||||
{
|
||||
// Check the 802.2 SNAP header.
|
||||
const struct snap_header_t* snap = (struct snap_header_t*)(packet + sizeof(struct ethernet_header_t));
|
||||
if (snap->dsap == SNAP_DSAP &&
|
||||
snap->ssap == SNAP_SSAP &&
|
||||
snap->control == SNAP_CONTROL)
|
||||
{
|
||||
if (memcmp(&snap->discriminator, &SNAP_APPLETALK, sizeof(snap->discriminator)) == 0)
|
||||
{
|
||||
// Handle an AppleTalk packet.
|
||||
const size_t payload_size = ntohs(ether->length) - sizeof(struct snap_header_t);
|
||||
const u_char* payload = packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t);
|
||||
|
||||
byte* copy = (byte*)malloc(payload_size);
|
||||
memcpy(copy, payload, payload_size);
|
||||
byte* copy = (byte*)malloc(payload_size);
|
||||
memcpy(copy, payload, payload_size);
|
||||
|
||||
// ELAP does not support short-form DDP, so this must be a long-form DDP packet.
|
||||
struct at_addr_t source, dest;
|
||||
if (payload_size >= sizeof(struct DDP_LONG))
|
||||
{
|
||||
// Extract the protocol address from the header.
|
||||
//
|
||||
// ELAP really shouldn't be looking at the header for the next level of the protocol stack,
|
||||
// but this is a convenient place to glean addresses for the AMT, a process that needs both
|
||||
// hardware and protocol addresses.
|
||||
struct DDP_LONG* header = (struct DDP_LONG*)copy;
|
||||
dest.network = (at_network_t)ntohs(header->dest_net);
|
||||
source.network = (at_network_t)ntohs(header->source_net);
|
||||
dest.node = header->dest_node;
|
||||
source.node = header->source_node;
|
||||
// ELAP does not support short-form DDP, so this must be a long-form DDP packet.
|
||||
struct at_addr_t source, dest;
|
||||
if (payload_size >= sizeof(struct DDP_LONG))
|
||||
{
|
||||
// Extract the protocol address from the header.
|
||||
//
|
||||
// ELAP really shouldn't be looking at the header for the next level of the protocol stack,
|
||||
// but this is a convenient place to glean addresses for the AMT, a process that needs both
|
||||
// hardware and protocol addresses.
|
||||
struct DDP_LONG* header = (struct DDP_LONG*)copy;
|
||||
dest.network = (at_network_t)ntohs(header->dest_net);
|
||||
source.network = (at_network_t)ntohs(header->source_net);
|
||||
dest.node = header->dest_node;
|
||||
source.node = header->source_node;
|
||||
|
||||
enqueue(&elap_port.in, dest, source, LAP_DDP_LONG, payload_size, copy);
|
||||
enqueue(&elap_port.in, dest, source, LAP_DDP_LONG, payload_size, copy);
|
||||
|
||||
aarp_glean(&source, ðer->source);
|
||||
}
|
||||
else
|
||||
atbridge_printf("ATBridge: Dropping invalid short ELAP frame.\n");
|
||||
}
|
||||
else if (memcmp(&snap->discriminator, &SNAP_AARP, sizeof(snap->discriminator)) == 0)
|
||||
{
|
||||
// Handle an AARP packet.
|
||||
struct aarp_header_t* aarp = (struct aarp_header_t*)(packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t));
|
||||
aarp->dest_proto_addr.addr.network = ntohs(aarp->dest_proto_addr.addr.network);
|
||||
aarp->source_proto_addr.addr.network = ntohs(aarp->source_proto_addr.addr.network);
|
||||
aarp->function = ntohs(aarp->function);
|
||||
aarp->hardware_type = ntohs(aarp->hardware_type);
|
||||
aarp->protocol_type = ntohs(aarp->protocol_type);
|
||||
aarp_handle_packet(aarp);
|
||||
}
|
||||
}
|
||||
}
|
||||
aarp_glean(&source, ðer->source);
|
||||
}
|
||||
else
|
||||
atbridge_printf("ATBridge: Dropping invalid short ELAP frame.\n");
|
||||
}
|
||||
else if (memcmp(&snap->discriminator, &SNAP_AARP, sizeof(snap->discriminator)) == 0)
|
||||
{
|
||||
// Handle an AARP packet.
|
||||
struct aarp_header_t* aarp = (struct aarp_header_t*)(packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t));
|
||||
aarp->dest_proto_addr.addr.network = ntohs(aarp->dest_proto_addr.addr.network);
|
||||
aarp->source_proto_addr.addr.network = ntohs(aarp->source_proto_addr.addr.network);
|
||||
aarp->function = ntohs(aarp->function);
|
||||
aarp->hardware_type = ntohs(aarp->hardware_type);
|
||||
aarp->protocol_type = ntohs(aarp->protocol_type);
|
||||
aarp_handle_packet(aarp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void elap_receive_all()
|
||||
{
|
||||
while (elap_receive_one());
|
||||
static void elap_receive_all() {
|
||||
while (elap_receive_one());
|
||||
}
|
||||
|
||||
void elap_process()
|
||||
{
|
||||
elap_receive_all();
|
||||
elap_send_all_queued();
|
||||
void elap_process() {
|
||||
elap_receive_all();
|
||||
elap_send_all_queued();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/** This module implements the LLAP port of the bridge. **/
|
||||
|
||||
|
@ -14,12 +14,12 @@
|
|||
#include "llap.h"
|
||||
|
||||
typedef enum {
|
||||
LLAP_DDP_SHORT = 0x01,
|
||||
LLAP_DDP_LONG = 0x02,
|
||||
LLAP_ENQ = 0x81,
|
||||
LLAP_ACK = 0x82,
|
||||
LLAP_RTS = 0x84,
|
||||
LLAP_CTS = 0x85
|
||||
LLAP_DDP_SHORT = 0x01,
|
||||
LLAP_DDP_LONG = 0x02,
|
||||
LLAP_ENQ = 0x81,
|
||||
LLAP_ACK = 0x82,
|
||||
LLAP_RTS = 0x84,
|
||||
LLAP_CTS = 0x85
|
||||
} LLAP_TYPES;
|
||||
|
||||
const unsigned int LLAP_PACKET_MAX = 603 /* bytes */;
|
||||
|
@ -31,290 +31,279 @@ const double GAP_TOLERANCE = 4.0;
|
|||
static struct packet_port_t llap_port;
|
||||
|
||||
typedef enum {
|
||||
DIALOG_READY,
|
||||
DIALOG_GOT_CTS,
|
||||
DIALOG_WAIT_IDG
|
||||
DIALOG_READY,
|
||||
DIALOG_GOT_CTS,
|
||||
DIALOG_WAIT_IDG
|
||||
} DIALOG_STATE;
|
||||
static DIALOG_STATE dialog_state;
|
||||
static double dialog_end_dcycs;
|
||||
static double last_frame_dcycs;
|
||||
|
||||
void llap_init()
|
||||
{
|
||||
dialog_state = DIALOG_READY;
|
||||
last_frame_dcycs = 0;
|
||||
port_init(&llap_port);
|
||||
void llap_init() {
|
||||
dialog_state = DIALOG_READY;
|
||||
last_frame_dcycs = 0;
|
||||
port_init(&llap_port);
|
||||
}
|
||||
|
||||
void llap_shutdown()
|
||||
{
|
||||
port_shutdown(&llap_port);
|
||||
void llap_shutdown() {
|
||||
port_shutdown(&llap_port);
|
||||
}
|
||||
|
||||
|
||||
/** Queue one data packet out from the bridge's LLAP port and into the guest. **/
|
||||
void llap_enqueue_out(struct packet_t* packet)
|
||||
{
|
||||
// Generate the RTS.
|
||||
struct packet_t* rts = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
rts->source.network = packet->source.network;
|
||||
rts->source.node = packet->source.node;
|
||||
rts->dest.network = packet->dest.network;
|
||||
rts->dest.node = packet->dest.node;
|
||||
rts->size = 0;
|
||||
rts->data = 0;
|
||||
rts->type = LLAP_RTS;
|
||||
enqueue_packet(&llap_port.out, rts);
|
||||
void llap_enqueue_out(struct packet_t* packet) {
|
||||
// Generate the RTS.
|
||||
struct packet_t* rts = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
rts->source.network = packet->source.network;
|
||||
rts->source.node = packet->source.node;
|
||||
rts->dest.network = packet->dest.network;
|
||||
rts->dest.node = packet->dest.node;
|
||||
rts->size = 0;
|
||||
rts->data = 0;
|
||||
rts->type = LLAP_RTS;
|
||||
enqueue_packet(&llap_port.out, rts);
|
||||
|
||||
// Enqueue the data.
|
||||
enqueue_packet(&llap_port.out, packet);
|
||||
// Enqueue the data.
|
||||
enqueue_packet(&llap_port.out, packet);
|
||||
}
|
||||
|
||||
struct packet_t* llap_dequeue_in()
|
||||
{
|
||||
return dequeue(&llap_port.in);
|
||||
struct packet_t* llap_dequeue_in() {
|
||||
return dequeue(&llap_port.in);
|
||||
}
|
||||
|
||||
static void llap_dump_packet(size_t size, byte data[])
|
||||
{
|
||||
if (size < LLAP_PACKET_MIN)
|
||||
atbridge_printf("LLAP short packet.\n");
|
||||
else if (size > LLAP_PACKET_MAX)
|
||||
atbridge_printf("LLAP long packet.\n");
|
||||
else
|
||||
{
|
||||
at_node_t dest = data[0];
|
||||
at_node_t source = data[1];
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
|
||||
const char* typeName = 0;
|
||||
switch (type)
|
||||
{
|
||||
case LLAP_DDP_SHORT:
|
||||
typeName = "DDP (short)";
|
||||
break;
|
||||
case LLAP_DDP_LONG:
|
||||
typeName = "DDP (long)";
|
||||
break;
|
||||
case LLAP_ENQ:
|
||||
typeName = "lapENQ";
|
||||
break;
|
||||
case LLAP_ACK:
|
||||
typeName = "lapACK";
|
||||
break;
|
||||
case LLAP_RTS:
|
||||
typeName = "lapRTS";
|
||||
break;
|
||||
case LLAP_CTS:
|
||||
typeName = "lapCTS";
|
||||
break;
|
||||
}
|
||||
static void llap_dump_packet(size_t size, byte data[]) {
|
||||
if (size < LLAP_PACKET_MIN)
|
||||
atbridge_printf("LLAP short packet.\n");
|
||||
else if (size > LLAP_PACKET_MAX)
|
||||
atbridge_printf("LLAP long packet.\n");
|
||||
else
|
||||
{
|
||||
at_node_t dest = data[0];
|
||||
at_node_t source = data[1];
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
|
||||
if (typeName)
|
||||
atbridge_printf("LLAP[%d->%d] %s: %d bytes.\n", source, dest, typeName, size);
|
||||
else
|
||||
atbridge_printf("LLAP[%d->%d] %x: %d bytes.\n", source, dest, type, size);
|
||||
|
||||
/*for (size_t i = 0; i < size; i++)
|
||||
atbridge_printf("%02x ", data[i]);
|
||||
atbridge_printf("\n");*/
|
||||
}
|
||||
const char* typeName = 0;
|
||||
switch (type)
|
||||
{
|
||||
case LLAP_DDP_SHORT:
|
||||
typeName = "DDP (short)";
|
||||
break;
|
||||
case LLAP_DDP_LONG:
|
||||
typeName = "DDP (long)";
|
||||
break;
|
||||
case LLAP_ENQ:
|
||||
typeName = "lapENQ";
|
||||
break;
|
||||
case LLAP_ACK:
|
||||
typeName = "lapACK";
|
||||
break;
|
||||
case LLAP_RTS:
|
||||
typeName = "lapRTS";
|
||||
break;
|
||||
case LLAP_CTS:
|
||||
typeName = "lapCTS";
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeName)
|
||||
atbridge_printf("LLAP[%d->%d] %s: %d bytes.\n", source, dest, typeName, size);
|
||||
else
|
||||
atbridge_printf("LLAP[%d->%d] %x: %d bytes.\n", source, dest, type, size);
|
||||
|
||||
/*for (size_t i = 0; i < size; i++)
|
||||
atbridge_printf("%02x ", data[i]);
|
||||
atbridge_printf("\n");*/
|
||||
}
|
||||
}
|
||||
|
||||
/** Reply to a control packet from the GS **/
|
||||
static void llap_reply_control(at_node_t dest, at_node_t source, LLAP_TYPES type)
|
||||
{
|
||||
struct at_addr_t dest_addr = { 0, dest };
|
||||
struct at_addr_t source_addr = { 0, source };
|
||||
static void llap_reply_control(at_node_t dest, at_node_t source, LLAP_TYPES type) {
|
||||
struct at_addr_t dest_addr = { 0, dest };
|
||||
struct at_addr_t source_addr = { 0, source };
|
||||
|
||||
// Insert control packets at the head of the queue contrary to normal FIFO queue operation
|
||||
// to ensure that control frames arrive in the intended order.
|
||||
insert(&llap_port.out, dest_addr, source_addr, type, 0, 0);
|
||||
// Insert control packets at the head of the queue contrary to normal FIFO queue operation
|
||||
// to ensure that control frames arrive in the intended order.
|
||||
insert(&llap_port.out, dest_addr, source_addr, type, 0, 0);
|
||||
}
|
||||
|
||||
/** Accept a data packet from the GS. **/
|
||||
static void llap_handle_data(size_t size, byte data[])
|
||||
{
|
||||
at_node_t dest = data[0];
|
||||
at_node_t source = data[1];
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
static void llap_handle_data(size_t size, byte data[]) {
|
||||
at_node_t dest = data[0];
|
||||
at_node_t source = data[1];
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
|
||||
const size_t data_size = size - 3;
|
||||
byte* data_copy = (byte*)malloc(data_size);
|
||||
memcpy(data_copy, data + 3, data_size);
|
||||
const size_t data_size = size - 3;
|
||||
byte* data_copy = (byte*)malloc(data_size);
|
||||
memcpy(data_copy, data + 3, data_size);
|
||||
|
||||
struct at_addr_t dest_addr = { 0, dest };
|
||||
struct at_addr_t source_addr = { 0, source };
|
||||
enqueue(&llap_port.in, dest_addr, source_addr, type, data_size, data_copy);
|
||||
struct at_addr_t dest_addr = { 0, dest };
|
||||
struct at_addr_t source_addr = { 0, source };
|
||||
enqueue(&llap_port.in, dest_addr, source_addr, type, data_size, data_copy);
|
||||
}
|
||||
|
||||
/** Accept a control packet from the GS. **/
|
||||
static void llap_handle_control(size_t size, byte data[])
|
||||
{
|
||||
at_node_t dest = data[0];
|
||||
at_node_t source = data[1];
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
static void llap_handle_control(size_t size, byte data[]) {
|
||||
at_node_t dest = data[0];
|
||||
at_node_t source = data[1];
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
|
||||
struct at_addr_t addr = { atbridge_get_net(), dest };
|
||||
struct at_addr_t addr = { atbridge_get_net(), dest };
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case LLAP_ENQ:
|
||||
// Require the GS to take a valid "client" address not known to be in use.
|
||||
if (dest > 127 || dest == 0 || atbridge_address_used(&addr))
|
||||
llap_reply_control(source, dest, LLAP_ACK);
|
||||
break;
|
||||
case LLAP_ACK:
|
||||
break;
|
||||
case LLAP_RTS:
|
||||
if (dest != at_broadcast_node)
|
||||
// The GS is trying to make a directed transmission. Provide the required RTS/CTS handshake.
|
||||
// Note that broadcast packets do not require a CTS.
|
||||
llap_reply_control(source, dest, LLAP_CTS);
|
||||
break;
|
||||
case LLAP_CTS:
|
||||
// The GS sent a CTS. If the bridge has pending data, prepare to deliver the packet.
|
||||
dialog_state = DIALOG_GOT_CTS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case LLAP_ENQ:
|
||||
// Require the GS to take a valid "client" address not known to be in use.
|
||||
if (dest > 127 || dest == 0 || atbridge_address_used(&addr))
|
||||
llap_reply_control(source, dest, LLAP_ACK);
|
||||
break;
|
||||
case LLAP_ACK:
|
||||
break;
|
||||
case LLAP_RTS:
|
||||
if (dest != at_broadcast_node)
|
||||
// The GS is trying to make a directed transmission. Provide the required RTS/CTS handshake.
|
||||
// Note that broadcast packets do not require a CTS.
|
||||
llap_reply_control(source, dest, LLAP_CTS);
|
||||
break;
|
||||
case LLAP_CTS:
|
||||
// The GS sent a CTS. If the bridge has pending data, prepare to deliver the packet.
|
||||
dialog_state = DIALOG_GOT_CTS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Occassionally, we receive an invalid packet from the GS. I'm unsure if this is due to a bug in GS/OS
|
||||
or, more likely, a bug in the SCC emulation. Regardless, when such a thing does occur, discard the
|
||||
current, corrupted dialog. Link errors are routine in real LocalTalk networks, and LocalTalk will recover.
|
||||
**/
|
||||
static void llap_reset_dialog()
|
||||
{
|
||||
dialog_state = DIALOG_READY;
|
||||
last_frame_dcycs = 0;
|
||||
or, more likely, a bug in the SCC emulation. Regardless, when such a thing does occur, discard the
|
||||
current, corrupted dialog. Link errors are routine in real LocalTalk networks, and LocalTalk will recover.
|
||||
**/
|
||||
static void llap_reset_dialog() {
|
||||
dialog_state = DIALOG_READY;
|
||||
last_frame_dcycs = 0;
|
||||
|
||||
// Discard packets until the queue is either empty or the next dialog starts (and dialogs begin with an RTS).
|
||||
while (true)
|
||||
{
|
||||
struct packet_t* packet = queue_peek(&llap_port.out);
|
||||
|
||||
if (packet && (packet->type != LLAP_RTS))
|
||||
{
|
||||
packet = dequeue(&llap_port.out);
|
||||
if (packet->data)
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
// Discard packets until the queue is either empty or the next dialog starts (and dialogs begin with an RTS).
|
||||
while (true)
|
||||
{
|
||||
struct packet_t* packet = queue_peek(&llap_port.out);
|
||||
|
||||
if (packet && (packet->type != LLAP_RTS))
|
||||
{
|
||||
packet = dequeue(&llap_port.out);
|
||||
if (packet->data)
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Transfer (send) one LLAP packet from the GS. **/
|
||||
void llap_enqueue_in(double dcycs, size_t size, byte data[])
|
||||
{
|
||||
atbridge_printf("<%0.0f> TX: ", dcycs);
|
||||
llap_dump_packet(size, data);
|
||||
void llap_enqueue_in(double dcycs, size_t size, byte data[]) {
|
||||
atbridge_printf("<%0.0f> TX: ", dcycs);
|
||||
llap_dump_packet(size, data);
|
||||
|
||||
if (size < LLAP_PACKET_MIN)
|
||||
atbridge_printf("ATBridge: Dropping LLAP short packet.\n");
|
||||
else if (size > LLAP_PACKET_MAX)
|
||||
atbridge_printf("ATBridge: Dropping LLAP long packet.\n");
|
||||
else
|
||||
{
|
||||
last_frame_dcycs = dcycs;
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
if (size < LLAP_PACKET_MIN)
|
||||
atbridge_printf("ATBridge: Dropping LLAP short packet.\n");
|
||||
else if (size > LLAP_PACKET_MAX)
|
||||
atbridge_printf("ATBridge: Dropping LLAP long packet.\n");
|
||||
else
|
||||
{
|
||||
last_frame_dcycs = dcycs;
|
||||
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case LLAP_DDP_SHORT:
|
||||
case LLAP_DDP_LONG:
|
||||
llap_handle_data(size, data);
|
||||
break;
|
||||
case LLAP_ENQ:
|
||||
case LLAP_ACK:
|
||||
case LLAP_RTS:
|
||||
case LLAP_CTS:
|
||||
llap_handle_control(size, data);
|
||||
break;
|
||||
default:
|
||||
// Intentionally check for valid types and ingore packets with invalid types.
|
||||
// Sometimes, the bridge gets invalid packets from the GS, which tends to break the bridge.
|
||||
atbridge_printf("ATBridge: Dropping LLAP packet with invalid type.\n");
|
||||
llap_reset_dialog();
|
||||
}
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case LLAP_DDP_SHORT:
|
||||
case LLAP_DDP_LONG:
|
||||
llap_handle_data(size, data);
|
||||
break;
|
||||
case LLAP_ENQ:
|
||||
case LLAP_ACK:
|
||||
case LLAP_RTS:
|
||||
case LLAP_CTS:
|
||||
llap_handle_control(size, data);
|
||||
break;
|
||||
default:
|
||||
// Intentionally check for valid types and ingore packets with invalid types.
|
||||
// Sometimes, the bridge gets invalid packets from the GS, which tends to break the bridge.
|
||||
atbridge_printf("ATBridge: Dropping LLAP packet with invalid type.\n");
|
||||
llap_reset_dialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Transfer (receive) one LLAP packet to the GS. **/
|
||||
void llap_dequeue_out(double dcycs, size_t* size, byte* data[])
|
||||
{
|
||||
*size = 0;
|
||||
void llap_dequeue_out(double dcycs, size_t* size, byte* data[]) {
|
||||
*size = 0;
|
||||
|
||||
// The LocalTalk protocol requires a minimum 400us gap between dialogs (called the IDG).
|
||||
// If necessary, wait for the IDG.
|
||||
if (dialog_state == DIALOG_WAIT_IDG)
|
||||
// The LocalTalk protocol requires a minimum 400us gap between dialogs (called the IDG).
|
||||
// If necessary, wait for the IDG.
|
||||
if (dialog_state == DIALOG_WAIT_IDG)
|
||||
{
|
||||
if ((dcycs - dialog_end_dcycs) >= LLAP_IDG)
|
||||
// The IDG is done.
|
||||
dialog_state = DIALOG_READY;
|
||||
else
|
||||
// Continue waiting for the IDG.
|
||||
return;
|
||||
}
|
||||
// The LocalTalk protocols requires a maximum 200us gap between frames within a dialog (called the IFG).
|
||||
// If we exceed the IFG, the bridge must be stuck in an incomplete or corrupt dialog. In this case,
|
||||
// discard the current dialog and try again.
|
||||
if ((dialog_state != DIALOG_READY) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IFG)))
|
||||
{
|
||||
llap_reset_dialog();
|
||||
atbridge_printf("ATBridge: Dialog reset due to IFG violation.\n");
|
||||
}
|
||||
|
||||
struct packet_t* packet = queue_peek(&llap_port.out);
|
||||
|
||||
if ((dialog_state == DIALOG_READY) && (packet) && !(packet->type & 0x80) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IDG)))
|
||||
{
|
||||
llap_reset_dialog();
|
||||
packet = queue_peek(&llap_port.out);
|
||||
atbridge_printf("ATBridge: Dialog reset due to IDG violation.\n");
|
||||
}
|
||||
|
||||
if (packet &&
|
||||
((packet->type & 0x80) || /* Pass along control frames without waiting for a CTS. */
|
||||
(!(packet->type & 0x80) && (packet->dest.node == at_broadcast_node) && (dialog_state == DIALOG_READY)) || /* Pass along broadcast frames, which don't wait for CTS frames. */
|
||||
(!(packet->type & 0x80) && (packet->dest.node != at_broadcast_node) && (dialog_state == DIALOG_GOT_CTS)))) /* Pass along directed frames only after receiving a CTS handshake. */
|
||||
{
|
||||
dequeue(&llap_port.out);
|
||||
|
||||
// Prepend the LLAP header.
|
||||
*size = packet->size + 3 + 2;
|
||||
*data = (byte*)malloc(*size);
|
||||
(*data)[0] = packet->dest.node;
|
||||
(*data)[1] = packet->source.node;
|
||||
(*data)[2] = packet->type;
|
||||
|
||||
// Insert the data into the new LLAP packet.
|
||||
if (*size)
|
||||
memcpy((*data) + 3, packet->data, packet->size);
|
||||
|
||||
// Fake a frame check sequence (FCS). Since our SCC emulation doesn't actually
|
||||
// check the FCS, the value of the FCS doesn't matter.
|
||||
(*data)[packet->size + 3 + 0] = 0xff;
|
||||
(*data)[packet->size + 3 + 1] = 0xff;
|
||||
|
||||
atbridge_printf("<%0.0f> RX: ", dcycs);
|
||||
llap_dump_packet(*size, *data);
|
||||
|
||||
if (packet->type & 0x80)
|
||||
dialog_state = DIALOG_READY;
|
||||
else
|
||||
{
|
||||
if ((dcycs - dialog_end_dcycs) >= LLAP_IDG)
|
||||
// The IDG is done.
|
||||
dialog_state = DIALOG_READY;
|
||||
else
|
||||
// Continue waiting for the IDG.
|
||||
return;
|
||||
// This was the last packet in the dialog.
|
||||
dialog_state = DIALOG_WAIT_IDG;
|
||||
dialog_end_dcycs = dcycs;
|
||||
}
|
||||
// The LocalTalk protocols requires a maximum 200us gap between frames within a dialog (called the IFG).
|
||||
// If we exceed the IFG, the bridge must be stuck in an incomplete or corrupt dialog. In this case,
|
||||
// discard the current dialog and try again.
|
||||
if ((dialog_state != DIALOG_READY) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IFG)))
|
||||
{
|
||||
llap_reset_dialog();
|
||||
atbridge_printf("ATBridge: Dialog reset due to IFG violation.\n");
|
||||
}
|
||||
|
||||
struct packet_t* packet = queue_peek(&llap_port.out);
|
||||
last_frame_dcycs = dcycs;
|
||||
|
||||
if ((dialog_state == DIALOG_READY) && (packet) && !(packet->type & 0x80) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IDG)))
|
||||
{
|
||||
llap_reset_dialog();
|
||||
packet = queue_peek(&llap_port.out);
|
||||
atbridge_printf("ATBridge: Dialog reset due to IDG violation.\n");
|
||||
}
|
||||
|
||||
if (packet &&
|
||||
((packet->type & 0x80) || /* Pass along control frames without waiting for a CTS. */
|
||||
(!(packet->type & 0x80) && (packet->dest.node == at_broadcast_node) && (dialog_state == DIALOG_READY)) || /* Pass along broadcast frames, which don't wait for CTS frames. */
|
||||
(!(packet->type & 0x80) && (packet->dest.node != at_broadcast_node) && (dialog_state == DIALOG_GOT_CTS)))) /* Pass along directed frames only after receiving a CTS handshake. */
|
||||
{
|
||||
dequeue(&llap_port.out);
|
||||
|
||||
// Prepend the LLAP header.
|
||||
*size = packet->size + 3 + 2;
|
||||
*data = (byte*)malloc(*size);
|
||||
(*data)[0] = packet->dest.node;
|
||||
(*data)[1] = packet->source.node;
|
||||
(*data)[2] = packet->type;
|
||||
|
||||
// Insert the data into the new LLAP packet.
|
||||
if (*size)
|
||||
memcpy((*data) + 3, packet->data, packet->size);
|
||||
|
||||
// Fake a frame check sequence (FCS). Since our SCC emulation doesn't actually
|
||||
// check the FCS, the value of the FCS doesn't matter.
|
||||
(*data)[packet->size + 3 + 0] = 0xff;
|
||||
(*data)[packet->size + 3 + 1] = 0xff;
|
||||
|
||||
atbridge_printf("<%0.0f> RX: ", dcycs);
|
||||
llap_dump_packet(*size, *data);
|
||||
|
||||
if (packet->type & 0x80)
|
||||
dialog_state = DIALOG_READY;
|
||||
else
|
||||
{
|
||||
// This was the last packet in the dialog.
|
||||
dialog_state = DIALOG_WAIT_IDG;
|
||||
dialog_end_dcycs = dcycs;
|
||||
}
|
||||
|
||||
last_frame_dcycs = dcycs;
|
||||
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pcap_delay.h"
|
||||
|
@ -17,143 +17,130 @@ static void* module = 0;
|
|||
#endif
|
||||
|
||||
|
||||
bool pcapdelay_load()
|
||||
{
|
||||
if (!pcapdelay_is_loaded())
|
||||
{
|
||||
bool pcapdelay_load() {
|
||||
if (!pcapdelay_is_loaded())
|
||||
{
|
||||
#ifdef WIN32
|
||||
module = LoadLibrary("wpcap.dll");
|
||||
module = LoadLibrary("wpcap.dll");
|
||||
#elif __linux__
|
||||
module = dlopen("libpcap.so", RTLD_LAZY);
|
||||
module = dlopen("libpcap.so", RTLD_LAZY);
|
||||
#endif
|
||||
}
|
||||
return pcapdelay_is_loaded();
|
||||
}
|
||||
return pcapdelay_is_loaded();
|
||||
}
|
||||
|
||||
bool pcapdelay_is_loaded()
|
||||
{
|
||||
bool pcapdelay_is_loaded() {
|
||||
#ifdef WIN32
|
||||
return module != NULL;
|
||||
return module != NULL;
|
||||
#elif __linux__
|
||||
return module != 0;
|
||||
return module != 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcapdelay_unload()
|
||||
{
|
||||
if (pcapdelay_is_loaded())
|
||||
{
|
||||
void pcapdelay_unload() {
|
||||
if (pcapdelay_is_loaded())
|
||||
{
|
||||
#ifdef WIN32
|
||||
FreeLibrary(module);
|
||||
module = NULL;
|
||||
FreeLibrary(module);
|
||||
module = NULL;
|
||||
#elif __linux__
|
||||
dlclose(module);
|
||||
module = 0;
|
||||
dlclose(module);
|
||||
module = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*PFNVOID)();
|
||||
|
||||
static PFNVOID delay_load(const char* proc, PFNVOID* ppfn)
|
||||
{
|
||||
if (pcapdelay_load() && proc && ppfn && !*ppfn)
|
||||
{
|
||||
static PFNVOID delay_load(const char* proc, PFNVOID* ppfn) {
|
||||
if (pcapdelay_load() && proc && ppfn && !*ppfn)
|
||||
{
|
||||
#ifdef WIN32
|
||||
*ppfn = (PFNVOID)GetProcAddress(module, proc);
|
||||
*ppfn = (PFNVOID)GetProcAddress(module, proc);
|
||||
#elif __linux__
|
||||
*ppfn = (PFNVOID)dlsym(module, proc);
|
||||
*ppfn = (PFNVOID)dlsym(module, proc);
|
||||
#endif
|
||||
}
|
||||
if (ppfn)
|
||||
return *ppfn;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (ppfn)
|
||||
return *ppfn;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcapdelay_freealldevs(pcap_if_t* a0)
|
||||
{
|
||||
typedef void (*PFN)(pcap_if_t*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_freealldevs", (PFNVOID*)&pfn)))
|
||||
(*pfn)(a0);
|
||||
void pcapdelay_freealldevs(pcap_if_t* a0) {
|
||||
typedef void (*PFN)(pcap_if_t*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_freealldevs", (PFNVOID*)&pfn)))
|
||||
(*pfn)(a0);
|
||||
}
|
||||
|
||||
pcap_t* pcapdelay_open_live(const char* a0, int a1, int a2, int a3, char* a4)
|
||||
{
|
||||
typedef pcap_t* (*PFN)(const char*, int, int, int, char*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_open_live", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2, a3, a4);
|
||||
else
|
||||
return 0;
|
||||
pcap_t* pcapdelay_open_live(const char* a0, int a1, int a2, int a3, char* a4) {
|
||||
typedef pcap_t* (*PFN)(const char*, int, int, int, char*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_open_live", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2, a3, a4);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcapdelay_close(pcap_t* a0)
|
||||
{
|
||||
typedef void (*PFN)(pcap_t*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_close", (PFNVOID*)&pfn)))
|
||||
(*pfn)(a0);
|
||||
void pcapdelay_close(pcap_t* a0) {
|
||||
typedef void (*PFN)(pcap_t*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_close", (PFNVOID*)&pfn)))
|
||||
(*pfn)(a0);
|
||||
}
|
||||
|
||||
int pcapdelay_findalldevs(pcap_if_t** a0, char* a1)
|
||||
{
|
||||
typedef int (*PFN)(pcap_if_t**, char*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_findalldevs", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1);
|
||||
else
|
||||
return 0;
|
||||
int pcapdelay_findalldevs(pcap_if_t** a0, char* a1) {
|
||||
typedef int (*PFN)(pcap_if_t**, char*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_findalldevs", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcapdelay_datalink(pcap_t* a0)
|
||||
{
|
||||
typedef int(*PFN)(pcap_t*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_datalink", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0);
|
||||
else
|
||||
return 0;
|
||||
int pcapdelay_datalink(pcap_t* a0) {
|
||||
typedef int (*PFN)(pcap_t*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_datalink", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcapdelay_setnonblock(pcap_t* a0, int a1, char* a2)
|
||||
{
|
||||
typedef int(*PFN)(pcap_t*, int, char*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_setnonblock", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2);
|
||||
else
|
||||
return 0;
|
||||
int pcapdelay_setnonblock(pcap_t* a0, int a1, char* a2) {
|
||||
typedef int (*PFN)(pcap_t*, int, char*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_setnonblock", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcapdelay_sendpacket(pcap_t* a0, u_char* a1, int a2)
|
||||
{
|
||||
typedef int(*PFN)(pcap_t*, u_char*, int);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_sendpacket", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2);
|
||||
else
|
||||
return 0;
|
||||
int pcapdelay_sendpacket(pcap_t* a0, u_char* a1, int a2) {
|
||||
typedef int (*PFN)(pcap_t*, u_char*, int);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_sendpacket", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const u_char* pcapdelay_next(pcap_t* a0, struct pcap_pkthdr* a1)
|
||||
{
|
||||
typedef const u_char*(*PFN)(pcap_t*, struct pcap_pkthdr*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_next", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1);
|
||||
else
|
||||
return 0;
|
||||
const u_char* pcapdelay_next(pcap_t* a0, struct pcap_pkthdr* a1) {
|
||||
typedef const u_char*(*PFN)(pcap_t*, struct pcap_pkthdr*);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_next", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcapdelay_dispatch(pcap_t* a0, int a1, pcap_handler a2, u_char* a3)
|
||||
{
|
||||
typedef const int(*PFN)(pcap_t *, int, pcap_handler, u_char *);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_dispatch", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2, a3);
|
||||
else
|
||||
return 0;
|
||||
int pcapdelay_dispatch(pcap_t* a0, int a1, pcap_handler a2, u_char* a3) {
|
||||
typedef const int (*PFN)(pcap_t *, int, pcap_handler, u_char *);
|
||||
static PFN pfn = 0;
|
||||
if ((pfn = (PFN)delay_load("pcap_dispatch", (PFNVOID*)&pfn)))
|
||||
return (*pfn)(a0, a1, a2, a3);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/** This module implements queues for storing and transferring packets within the bridge. **/
|
||||
|
||||
|
@ -11,117 +11,107 @@
|
|||
#include "atalk.h"
|
||||
#include "port.h"
|
||||
|
||||
void port_init(struct packet_port_t* port)
|
||||
{
|
||||
if (port)
|
||||
{
|
||||
queue_init(&port->in);
|
||||
queue_init(&port->out);
|
||||
}
|
||||
void port_init(struct packet_port_t* port) {
|
||||
if (port)
|
||||
{
|
||||
queue_init(&port->in);
|
||||
queue_init(&port->out);
|
||||
}
|
||||
}
|
||||
|
||||
void port_shutdown(struct packet_port_t* port)
|
||||
{
|
||||
if (port)
|
||||
{
|
||||
queue_shutdown(&port->in);
|
||||
queue_shutdown(&port->out);
|
||||
}
|
||||
void port_shutdown(struct packet_port_t* port) {
|
||||
if (port)
|
||||
{
|
||||
queue_shutdown(&port->in);
|
||||
queue_shutdown(&port->out);
|
||||
}
|
||||
}
|
||||
|
||||
void queue_init(struct packet_queue_t* queue)
|
||||
{
|
||||
if (queue)
|
||||
{
|
||||
queue->head = queue->tail = 0;
|
||||
}
|
||||
void queue_init(struct packet_queue_t* queue) {
|
||||
if (queue)
|
||||
{
|
||||
queue->head = queue->tail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void queue_shutdown(struct packet_queue_t* queue)
|
||||
{
|
||||
if (queue)
|
||||
{
|
||||
struct packet_t* packet = dequeue(queue);
|
||||
while (packet)
|
||||
{
|
||||
if (packet->data)
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
packet = dequeue(queue);
|
||||
}
|
||||
}
|
||||
void queue_shutdown(struct packet_queue_t* queue) {
|
||||
if (queue)
|
||||
{
|
||||
struct packet_t* packet = dequeue(queue);
|
||||
while (packet)
|
||||
{
|
||||
if (packet->data)
|
||||
free(packet->data);
|
||||
free(packet);
|
||||
packet = dequeue(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enqueue(struct packet_queue_t* queue, struct at_addr_t dest, struct at_addr_t source, byte type, size_t size, byte data[])
|
||||
{
|
||||
if (!queue)
|
||||
return;
|
||||
void enqueue(struct packet_queue_t* queue, struct at_addr_t dest, struct at_addr_t source, byte type, size_t size, byte data[]) {
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
packet->dest.network = dest.network;
|
||||
packet->dest.node = dest.node;
|
||||
packet->source.network = source.network;
|
||||
packet->source.node = source.node;
|
||||
packet->type = type;
|
||||
packet->size = size;
|
||||
packet->data = data;
|
||||
enqueue_packet(queue, packet);
|
||||
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
packet->dest.network = dest.network;
|
||||
packet->dest.node = dest.node;
|
||||
packet->source.network = source.network;
|
||||
packet->source.node = source.node;
|
||||
packet->type = type;
|
||||
packet->size = size;
|
||||
packet->data = data;
|
||||
enqueue_packet(queue, packet);
|
||||
}
|
||||
|
||||
void enqueue_packet(struct packet_queue_t* queue, struct packet_t* packet)
|
||||
{
|
||||
packet->next = 0;
|
||||
void enqueue_packet(struct packet_queue_t* queue, struct packet_t* packet) {
|
||||
packet->next = 0;
|
||||
|
||||
if (queue->tail)
|
||||
queue->tail->next = packet;
|
||||
else
|
||||
queue->head = packet;
|
||||
queue->tail = packet;
|
||||
if (queue->tail)
|
||||
queue->tail->next = packet;
|
||||
else
|
||||
queue->head = packet;
|
||||
queue->tail = packet;
|
||||
}
|
||||
|
||||
void insert(struct packet_queue_t* queue, struct at_addr_t dest, struct at_addr_t source, byte type, size_t size, byte data[])
|
||||
{
|
||||
if (!queue)
|
||||
return;
|
||||
void insert(struct packet_queue_t* queue, struct at_addr_t dest, struct at_addr_t source, byte type, size_t size, byte data[]) {
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
packet->dest.network = dest.network;
|
||||
packet->dest.node = dest.node;
|
||||
packet->source.network = source.network;
|
||||
packet->source.node = source.node;
|
||||
packet->type = type;
|
||||
packet->size = size;
|
||||
packet->data = data;
|
||||
insert_packet(queue, packet);
|
||||
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
|
||||
packet->dest.network = dest.network;
|
||||
packet->dest.node = dest.node;
|
||||
packet->source.network = source.network;
|
||||
packet->source.node = source.node;
|
||||
packet->type = type;
|
||||
packet->size = size;
|
||||
packet->data = data;
|
||||
insert_packet(queue, packet);
|
||||
}
|
||||
|
||||
void insert_packet(struct packet_queue_t* queue, struct packet_t* packet)
|
||||
{
|
||||
packet->next = queue->head;
|
||||
queue->head = packet;
|
||||
if (!queue->tail)
|
||||
queue->tail = queue->head;
|
||||
void insert_packet(struct packet_queue_t* queue, struct packet_t* packet) {
|
||||
packet->next = queue->head;
|
||||
queue->head = packet;
|
||||
if (!queue->tail)
|
||||
queue->tail = queue->head;
|
||||
}
|
||||
|
||||
struct packet_t* dequeue(struct packet_queue_t* queue)
|
||||
{
|
||||
if (queue && queue->head)
|
||||
{
|
||||
struct packet_t* packet = queue->head;
|
||||
if (queue->tail == queue->head)
|
||||
queue->tail = queue->head = 0;
|
||||
else
|
||||
queue->head = packet->next;
|
||||
return packet;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
struct packet_t* dequeue(struct packet_queue_t* queue) {
|
||||
if (queue && queue->head)
|
||||
{
|
||||
struct packet_t* packet = queue->head;
|
||||
if (queue->tail == queue->head)
|
||||
queue->tail = queue->head = 0;
|
||||
else
|
||||
queue->head = packet->next;
|
||||
return packet;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct packet_t* queue_peek(struct packet_queue_t* queue)
|
||||
{
|
||||
if (queue)
|
||||
return queue->head;
|
||||
else
|
||||
return 0;
|
||||
struct packet_t* queue_peek(struct packet_queue_t* queue) {
|
||||
if (queue)
|
||||
return queue->head;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
649
src/clock.c
649
src/clock.c
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include <time.h>
|
||||
|
@ -16,419 +16,396 @@
|
|||
#endif
|
||||
|
||||
extern int Verbose;
|
||||
extern word32 g_vbl_count; // OG change int to word32
|
||||
extern word32 g_vbl_count; // OG change int to word32
|
||||
extern int g_rom_version;
|
||||
extern int g_config_gsplus_update_needed;
|
||||
|
||||
#define CLK_IDLE 1
|
||||
#define CLK_TIME 2
|
||||
#define CLK_INTERNAL 3
|
||||
#define CLK_BRAM1 4
|
||||
#define CLK_BRAM2 5
|
||||
#define CLK_IDLE 1
|
||||
#define CLK_TIME 2
|
||||
#define CLK_INTERNAL 3
|
||||
#define CLK_BRAM1 4
|
||||
#define CLK_BRAM2 5
|
||||
|
||||
int g_clk_mode = CLK_IDLE;
|
||||
int g_clk_read = 0;
|
||||
int g_clk_reg1 = 0;
|
||||
int g_clk_mode = CLK_IDLE;
|
||||
int g_clk_read = 0;
|
||||
int g_clk_reg1 = 0;
|
||||
|
||||
extern int g_c033_data;
|
||||
extern int g_c034_val;
|
||||
|
||||
byte g_bram[2][256];
|
||||
byte *g_bram_ptr = &(g_bram[0][0]);
|
||||
byte g_temp_boot_slot = 254;
|
||||
byte g_orig_boot_slot = 0;
|
||||
byte g_bram[2][256];
|
||||
byte *g_bram_ptr = &(g_bram[0][0]);
|
||||
byte g_temp_boot_slot = 254;
|
||||
byte g_orig_boot_slot = 0;
|
||||
|
||||
word32 g_clk_cur_time = 0xa0000000;
|
||||
int g_clk_next_vbl_update = 0;
|
||||
word32 g_clk_cur_time = 0xa0000000;
|
||||
int g_clk_next_vbl_update = 0;
|
||||
|
||||
double
|
||||
get_dtime()
|
||||
{
|
||||
double get_dtime() {
|
||||
#ifndef _WIN32
|
||||
struct timeval tp1;
|
||||
double dsec;
|
||||
double dusec;
|
||||
struct timeval tp1;
|
||||
double dsec;
|
||||
double dusec;
|
||||
#endif
|
||||
double dtime;
|
||||
double dtime;
|
||||
|
||||
/* Routine used to return actual system time as a double */
|
||||
/* No routine cares about the absolute value, only deltas--maybe */
|
||||
/* take advantage of that in future to increase usec accuracy */
|
||||
/* Routine used to return actual system time as a double */
|
||||
/* No routine cares about the absolute value, only deltas--maybe */
|
||||
/* take advantage of that in future to increase usec accuracy */
|
||||
|
||||
#ifdef _WIN32
|
||||
dtime = timeGetTime() / 1000.0;
|
||||
dtime = timeGetTime() / 1000.0;
|
||||
#else
|
||||
|
||||
# ifdef SOLARIS
|
||||
gettimeofday(&tp1, (void *)0);
|
||||
gettimeofday(&tp1, (void *)0);
|
||||
# else
|
||||
gettimeofday(&tp1, (struct timezone *)0);
|
||||
gettimeofday(&tp1, (struct timezone *)0);
|
||||
# endif
|
||||
|
||||
dsec = (double)tp1.tv_sec;
|
||||
dusec = (double)tp1.tv_usec;
|
||||
dsec = (double)tp1.tv_sec;
|
||||
dusec = (double)tp1.tv_usec;
|
||||
|
||||
dtime = dsec + (dusec / (1000.0 * 1000.0));
|
||||
dtime = dsec + (dusec / (1000.0 * 1000.0));
|
||||
#endif
|
||||
|
||||
return dtime;
|
||||
return dtime;
|
||||
}
|
||||
|
||||
int
|
||||
micro_sleep(double dtime)
|
||||
{
|
||||
int micro_sleep(double dtime) {
|
||||
#ifndef _WIN32
|
||||
struct timeval Timer;
|
||||
int ret;
|
||||
struct timeval Timer;
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if(dtime <= 0.0) {
|
||||
return 0;
|
||||
}
|
||||
if(dtime >= 1.0) {
|
||||
halt_printf("micro_sleep called with %f!!\n", dtime);
|
||||
return -1;
|
||||
}
|
||||
if(dtime <= 0.0) {
|
||||
return 0;
|
||||
}
|
||||
if(dtime >= 1.0) {
|
||||
halt_printf("micro_sleep called with %f!!\n", dtime);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("usleep: %f\n", dtime);
|
||||
printf("usleep: %f\n", dtime);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
Sleep((DWORD)(dtime * 1000));
|
||||
Sleep((DWORD)(dtime * 1000));
|
||||
#else
|
||||
Timer.tv_sec = 0;
|
||||
Timer.tv_usec = (dtime * 1000000.0);
|
||||
if( (ret = select(0, 0, 0, 0, &Timer)) < 0) {
|
||||
glogf("micro_sleep (select) ret: %d, errno: %d", ret, errno);
|
||||
return -1;
|
||||
}
|
||||
Timer.tv_sec = 0;
|
||||
Timer.tv_usec = (dtime * 1000000.0);
|
||||
if( (ret = select(0, 0, 0, 0, &Timer)) < 0) {
|
||||
glogf("micro_sleep (select) ret: %d, errno: %d", ret, errno);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
clk_bram_zero()
|
||||
{
|
||||
int i, j;
|
||||
void clk_bram_zero() {
|
||||
int i, j;
|
||||
|
||||
/* zero out all bram */
|
||||
for(i = 0; i < 2; i++) {
|
||||
for(j = 0; j < 256; j++) {
|
||||
g_bram[i][j] = 0;
|
||||
}
|
||||
}
|
||||
g_bram_ptr = &(g_bram[0][0]);
|
||||
/* zero out all bram */
|
||||
for(i = 0; i < 2; i++) {
|
||||
for(j = 0; j < 256; j++) {
|
||||
g_bram[i][j] = 0;
|
||||
}
|
||||
}
|
||||
g_bram_ptr = &(g_bram[0][0]);
|
||||
}
|
||||
|
||||
void
|
||||
clk_bram_set(int bram_num, int offset, int val)
|
||||
{
|
||||
g_bram[bram_num][offset] = val;
|
||||
void clk_bram_set(int bram_num, int offset, int val) {
|
||||
g_bram[bram_num][offset] = val;
|
||||
}
|
||||
|
||||
|
||||
extern void x_clk_setup_bram_version();
|
||||
|
||||
void
|
||||
clk_setup_bram_version()
|
||||
{
|
||||
x_clk_setup_bram_version();
|
||||
void clk_setup_bram_version() {
|
||||
x_clk_setup_bram_version();
|
||||
}
|
||||
|
||||
void
|
||||
clk_write_bram(FILE *fconf)
|
||||
{
|
||||
int i, j, k;
|
||||
void clk_write_bram(FILE *fconf) {
|
||||
int i, j, k;
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
fprintf(fconf, "\n");
|
||||
for(j = 0; j < 256; j += 16) {
|
||||
fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j);
|
||||
for(k = 0; k < 16; k++) {
|
||||
fprintf(fconf, " %02x", g_bram[i][j+k]);
|
||||
}
|
||||
fprintf(fconf, "\n");
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 2; i++) {
|
||||
fprintf(fconf, "\n");
|
||||
for(j = 0; j < 256; j += 16) {
|
||||
fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j);
|
||||
for(k = 0; k < 16; k++) {
|
||||
fprintf(fconf, " %02x", g_bram[i][j+k]);
|
||||
}
|
||||
fprintf(fconf, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clk_calculate_bram_checksum(void) {
|
||||
int checksum = 0;
|
||||
int i;
|
||||
if (g_bram_ptr[251] == 0xff) {
|
||||
// Only make the checksum valid if we have non-zeron data!
|
||||
// Otherwise you have very valid zeroes, which confuses the GS firmware mightily.
|
||||
for (i = 250; i >= 0; i--) {
|
||||
checksum = (checksum & 0xFFFF) << 1;
|
||||
checksum = (checksum & 0xFFFF)
|
||||
+ g_bram_ptr[i]
|
||||
+ ((int)g_bram_ptr[i + 1] << 8)
|
||||
+ (checksum >> 16);
|
||||
}
|
||||
checksum &= 0xFFFF;
|
||||
checksum += ((checksum ^ 0xAAAA) << 16);
|
||||
void clk_calculate_bram_checksum(void) {
|
||||
int checksum = 0;
|
||||
int i;
|
||||
if (g_bram_ptr[251] == 0xff) {
|
||||
// Only make the checksum valid if we have non-zeron data!
|
||||
// Otherwise you have very valid zeroes, which confuses the GS firmware mightily.
|
||||
for (i = 250; i >= 0; i--) {
|
||||
checksum = (checksum & 0xFFFF) << 1;
|
||||
checksum = (checksum & 0xFFFF)
|
||||
+ g_bram_ptr[i]
|
||||
+ ((int)g_bram_ptr[i + 1] << 8)
|
||||
+ (checksum >> 16);
|
||||
}
|
||||
checksum &= 0xFFFF;
|
||||
checksum += ((checksum ^ 0xAAAA) << 16);
|
||||
#if defined(GSPLUS_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
|
||||
g_bram_ptr[252] = (checksum & 0xFF);
|
||||
g_bram_ptr[253] = (checksum >> 8);
|
||||
g_bram_ptr[254] = (checksum >> 16);
|
||||
g_bram_ptr[255] = (checksum >> 24);
|
||||
g_bram_ptr[252] = (checksum & 0xFF);
|
||||
g_bram_ptr[253] = (checksum >> 8);
|
||||
g_bram_ptr[254] = (checksum >> 16);
|
||||
g_bram_ptr[255] = (checksum >> 24);
|
||||
#else
|
||||
g_bram_ptr[255] = (checksum & 0xFF);
|
||||
g_bram_ptr[254] = (checksum >> 8);
|
||||
g_bram_ptr[253] = (checksum >> 16);
|
||||
g_bram_ptr[252] = (checksum >> 24);
|
||||
g_bram_ptr[255] = (checksum & 0xFF);
|
||||
g_bram_ptr[254] = (checksum >> 8);
|
||||
g_bram_ptr[253] = (checksum >> 16);
|
||||
g_bram_ptr[252] = (checksum >> 24);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
update_cur_time()
|
||||
{
|
||||
struct tm *tm_ptr;
|
||||
time_t cur_time;
|
||||
unsigned int secs, secs2;
|
||||
void update_cur_time() {
|
||||
struct tm *tm_ptr;
|
||||
time_t cur_time;
|
||||
unsigned int secs, secs2;
|
||||
|
||||
|
||||
#ifdef UNDER_CE // OG Not supported on WIndows CE
|
||||
/*
|
||||
SYSTEMTIME stime;
|
||||
FILETIME ftime;
|
||||
GetLocalTime(&stime);
|
||||
SystemTimeToFileTime(&stime,&ftime);
|
||||
cur_time = ftime.dwLowDateTime;
|
||||
*/
|
||||
cur_time = time(0);
|
||||
#ifdef UNDER_CE // OG Not supported on WIndows CE
|
||||
/*
|
||||
SYSTEMTIME stime;
|
||||
FILETIME ftime;
|
||||
GetLocalTime(&stime);
|
||||
SystemTimeToFileTime(&stime,&ftime);
|
||||
cur_time = ftime.dwLowDateTime;
|
||||
*/
|
||||
cur_time = time(0);
|
||||
|
||||
secs=0;
|
||||
secs2=0;
|
||||
secs=0;
|
||||
secs2=0;
|
||||
|
||||
#else
|
||||
cur_time = time(0);
|
||||
cur_time = time(0);
|
||||
|
||||
/* Figure out the timezone (effectively) by diffing two times. */
|
||||
/* this is probably not right for a few hours around daylight savings*/
|
||||
/* time transition */
|
||||
secs2 = (unsigned int)mktime(gmtime(&cur_time));
|
||||
tm_ptr = localtime(&cur_time);
|
||||
secs = (unsigned int)mktime(tm_ptr);
|
||||
/* Figure out the timezone (effectively) by diffing two times. */
|
||||
/* this is probably not right for a few hours around daylight savings*/
|
||||
/* time transition */
|
||||
secs2 = (unsigned int)mktime(gmtime(&cur_time));
|
||||
tm_ptr = localtime(&cur_time);
|
||||
secs = (unsigned int)mktime(tm_ptr);
|
||||
|
||||
#ifdef MAC
|
||||
/* Mac OS X's mktime function modifies the tm_ptr passed in for */
|
||||
/* the CDT timezone and breaks this algorithm. So on a Mac, we */
|
||||
/* will use the tm_ptr->gmtoff member to correct the time */
|
||||
secs = secs + tm_ptr->tm_gmtoff;
|
||||
/* Mac OS X's mktime function modifies the tm_ptr passed in for */
|
||||
/* the CDT timezone and breaks this algorithm. So on a Mac, we */
|
||||
/* will use the tm_ptr->gmtoff member to correct the time */
|
||||
secs = secs + tm_ptr->tm_gmtoff;
|
||||
#else
|
||||
secs = (unsigned int)cur_time - (secs2 - secs);
|
||||
secs = (unsigned int)cur_time - (secs2 - secs);
|
||||
|
||||
if(tm_ptr->tm_isdst) {
|
||||
/* adjust for daylight savings time */
|
||||
secs += 3600;
|
||||
}
|
||||
if(tm_ptr->tm_isdst) {
|
||||
/* adjust for daylight savings time */
|
||||
secs += 3600;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* add in secs to make date based on Apple Jan 1, 1904 instead of */
|
||||
/* Unix's Jan 1, 1970 */
|
||||
/* So add in 66 years and 17 leap year days (1904 is a leap year) */
|
||||
secs += ((66*365) + 17) * (24*3600);
|
||||
/* add in secs to make date based on Apple Jan 1, 1904 instead of */
|
||||
/* Unix's Jan 1, 1970 */
|
||||
/* So add in 66 years and 17 leap year days (1904 is a leap year) */
|
||||
secs += ((66*365) + 17) * (24*3600);
|
||||
|
||||
g_clk_cur_time = secs;
|
||||
g_clk_cur_time = secs;
|
||||
|
||||
clk_printf("Update g_clk_cur_time to %08x\n", g_clk_cur_time);
|
||||
g_clk_next_vbl_update = g_vbl_count + 5;
|
||||
clk_printf("Update g_clk_cur_time to %08x\n", g_clk_cur_time);
|
||||
g_clk_next_vbl_update = g_vbl_count + 5;
|
||||
}
|
||||
|
||||
/* clock_update called by sim65816 every VBL */
|
||||
void
|
||||
clock_update()
|
||||
{
|
||||
/* Nothing to do */
|
||||
void clock_update() {
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
void
|
||||
clock_update_if_needed()
|
||||
{
|
||||
int diff;
|
||||
void clock_update_if_needed() {
|
||||
int diff;
|
||||
|
||||
diff = g_clk_next_vbl_update - g_vbl_count;
|
||||
if(diff < 0 || diff > 60) {
|
||||
/* Been a while, re-read the clock */
|
||||
update_cur_time();
|
||||
}
|
||||
diff = g_clk_next_vbl_update - g_vbl_count;
|
||||
if(diff < 0 || diff > 60) {
|
||||
/* Been a while, re-read the clock */
|
||||
update_cur_time();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clock_write_c034(word32 val)
|
||||
{
|
||||
g_c034_val = val & 0x7f;
|
||||
if((val & 0x80) != 0) {
|
||||
if((val & 0x20) == 0) {
|
||||
printf("c034 write not last = 1\n");
|
||||
/* set_halt(1); */
|
||||
}
|
||||
do_clock_data();
|
||||
}
|
||||
void clock_write_c034(word32 val) {
|
||||
g_c034_val = val & 0x7f;
|
||||
if((val & 0x80) != 0) {
|
||||
if((val & 0x20) == 0) {
|
||||
printf("c034 write not last = 1\n");
|
||||
/* set_halt(1); */
|
||||
}
|
||||
do_clock_data();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
do_clock_data()
|
||||
{
|
||||
word32 mask;
|
||||
int read;
|
||||
int op;
|
||||
void do_clock_data() {
|
||||
word32 mask;
|
||||
int read;
|
||||
int op;
|
||||
|
||||
clk_printf("In do_clock_data, g_clk_mode: %02x\n", g_clk_mode);
|
||||
clk_printf("In do_clock_data, g_clk_mode: %02x\n", g_clk_mode);
|
||||
|
||||
read = g_c034_val & 0x40;
|
||||
switch(g_clk_mode) {
|
||||
case CLK_IDLE:
|
||||
g_clk_read = (g_c033_data >> 7) & 1;
|
||||
g_clk_reg1 = (g_c033_data >> 2) & 3;
|
||||
op = (g_c033_data >> 4) & 7;
|
||||
if(!read) {
|
||||
/* write */
|
||||
switch(op) {
|
||||
case 0x0: /* Read/write seconds register */
|
||||
g_clk_mode = CLK_TIME;
|
||||
clock_update_if_needed();
|
||||
break;
|
||||
case 0x3: /* internal registers */
|
||||
g_clk_mode = CLK_INTERNAL;
|
||||
if(g_clk_reg1 & 0x2) {
|
||||
/* extend BRAM read */
|
||||
g_clk_mode = CLK_BRAM2;
|
||||
g_clk_reg1 = (g_c033_data & 7) << 5;
|
||||
}
|
||||
break;
|
||||
case 0x2: /* read/write ram 0x10-0x13 */
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
g_clk_reg1 += 0x10;
|
||||
break;
|
||||
case 0x4: /* read/write ram 0x00-0x0f */
|
||||
case 0x5: case 0x6: case 0x7:
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
g_clk_reg1 = (g_c033_data >> 2) & 0xf;
|
||||
break;
|
||||
default:
|
||||
halt_printf("Bad c033_data in CLK_IDLE: %02x\n",
|
||||
g_c033_data);
|
||||
}
|
||||
} else {
|
||||
printf("clk read from IDLE mode!\n");
|
||||
/* set_halt(1); */
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
break;
|
||||
case CLK_BRAM2:
|
||||
if(!read) {
|
||||
/* get more bits of bram addr */
|
||||
if((g_c033_data & 0x83) == 0x00) {
|
||||
/* more address bits */
|
||||
g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f);
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
} else {
|
||||
halt_printf("CLK_BRAM2: c033_data: %02x!\n",
|
||||
g_c033_data);
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
} else {
|
||||
halt_printf("CLK_BRAM2: clock read!\n");
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
break;
|
||||
case CLK_BRAM1:
|
||||
/* access battery ram addr g_clk_reg1 */
|
||||
if(read) {
|
||||
if(g_clk_read) {
|
||||
/* Yup, read */
|
||||
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)){
|
||||
// Modify boot slot
|
||||
g_c033_data = g_temp_boot_slot;
|
||||
clk_calculate_bram_checksum();
|
||||
} else {
|
||||
g_c033_data = g_bram_ptr[g_clk_reg1];
|
||||
}
|
||||
clk_printf("Reading BRAM loc %02x: %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
} else {
|
||||
halt_printf("CLK_BRAM1: said wr, now read\n");
|
||||
}
|
||||
} else {
|
||||
if(g_clk_read) {
|
||||
halt_printf("CLK_BRAM1: said rd, now write\n");
|
||||
} else {
|
||||
/* Yup, write */
|
||||
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) {
|
||||
// Modify boot slot
|
||||
g_bram_ptr[g_clk_reg1] = g_temp_boot_slot;
|
||||
clk_calculate_bram_checksum();
|
||||
} else {
|
||||
g_bram_ptr[g_clk_reg1] = g_c033_data;
|
||||
}
|
||||
clk_printf("Writing BRAM loc %02x with %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
g_config_gsplus_update_needed = 1;
|
||||
}
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
case CLK_TIME:
|
||||
if(read) {
|
||||
if(g_clk_read == 0) {
|
||||
halt_printf("Reading time, but in set mode!\n");
|
||||
}
|
||||
g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) &
|
||||
0xff;
|
||||
clk_printf("Returning time byte %d: %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
} else {
|
||||
/* Write */
|
||||
if(g_clk_read) {
|
||||
halt_printf("Write time, but in read mode!\n");
|
||||
}
|
||||
clk_printf("Writing TIME loc %d with %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
mask = 0xff << (8 * g_clk_reg1);
|
||||
read = g_c034_val & 0x40;
|
||||
switch(g_clk_mode) {
|
||||
case CLK_IDLE:
|
||||
g_clk_read = (g_c033_data >> 7) & 1;
|
||||
g_clk_reg1 = (g_c033_data >> 2) & 3;
|
||||
op = (g_c033_data >> 4) & 7;
|
||||
if(!read) {
|
||||
/* write */
|
||||
switch(op) {
|
||||
case 0x0: /* Read/write seconds register */
|
||||
g_clk_mode = CLK_TIME;
|
||||
clock_update_if_needed();
|
||||
break;
|
||||
case 0x3: /* internal registers */
|
||||
g_clk_mode = CLK_INTERNAL;
|
||||
if(g_clk_reg1 & 0x2) {
|
||||
/* extend BRAM read */
|
||||
g_clk_mode = CLK_BRAM2;
|
||||
g_clk_reg1 = (g_c033_data & 7) << 5;
|
||||
}
|
||||
break;
|
||||
case 0x2: /* read/write ram 0x10-0x13 */
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
g_clk_reg1 += 0x10;
|
||||
break;
|
||||
case 0x4: /* read/write ram 0x00-0x0f */
|
||||
case 0x5: case 0x6: case 0x7:
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
g_clk_reg1 = (g_c033_data >> 2) & 0xf;
|
||||
break;
|
||||
default:
|
||||
halt_printf("Bad c033_data in CLK_IDLE: %02x\n",
|
||||
g_c033_data);
|
||||
}
|
||||
} else {
|
||||
printf("clk read from IDLE mode!\n");
|
||||
/* set_halt(1); */
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
break;
|
||||
case CLK_BRAM2:
|
||||
if(!read) {
|
||||
/* get more bits of bram addr */
|
||||
if((g_c033_data & 0x83) == 0x00) {
|
||||
/* more address bits */
|
||||
g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f);
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
} else {
|
||||
halt_printf("CLK_BRAM2: c033_data: %02x!\n",
|
||||
g_c033_data);
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
} else {
|
||||
halt_printf("CLK_BRAM2: clock read!\n");
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
break;
|
||||
case CLK_BRAM1:
|
||||
/* access battery ram addr g_clk_reg1 */
|
||||
if(read) {
|
||||
if(g_clk_read) {
|
||||
/* Yup, read */
|
||||
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) {
|
||||
// Modify boot slot
|
||||
g_c033_data = g_temp_boot_slot;
|
||||
clk_calculate_bram_checksum();
|
||||
} else {
|
||||
g_c033_data = g_bram_ptr[g_clk_reg1];
|
||||
}
|
||||
clk_printf("Reading BRAM loc %02x: %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
} else {
|
||||
halt_printf("CLK_BRAM1: said wr, now read\n");
|
||||
}
|
||||
} else {
|
||||
if(g_clk_read) {
|
||||
halt_printf("CLK_BRAM1: said rd, now write\n");
|
||||
} else {
|
||||
/* Yup, write */
|
||||
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) {
|
||||
// Modify boot slot
|
||||
g_bram_ptr[g_clk_reg1] = g_temp_boot_slot;
|
||||
clk_calculate_bram_checksum();
|
||||
} else {
|
||||
g_bram_ptr[g_clk_reg1] = g_c033_data;
|
||||
}
|
||||
clk_printf("Writing BRAM loc %02x with %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
g_config_gsplus_update_needed = 1;
|
||||
}
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
case CLK_TIME:
|
||||
if(read) {
|
||||
if(g_clk_read == 0) {
|
||||
halt_printf("Reading time, but in set mode!\n");
|
||||
}
|
||||
g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) &
|
||||
0xff;
|
||||
clk_printf("Returning time byte %d: %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
} else {
|
||||
/* Write */
|
||||
if(g_clk_read) {
|
||||
halt_printf("Write time, but in read mode!\n");
|
||||
}
|
||||
clk_printf("Writing TIME loc %d with %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
mask = 0xff << (8 * g_clk_reg1);
|
||||
|
||||
g_clk_cur_time = (g_clk_cur_time & (~mask)) |
|
||||
((g_c033_data & 0xff) << (8 * g_clk_reg1));
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
case CLK_INTERNAL:
|
||||
if(read) {
|
||||
printf("Attempting to read internal reg %02x!\n",
|
||||
g_clk_reg1);
|
||||
} else {
|
||||
switch(g_clk_reg1) {
|
||||
case 0x0: /* test register */
|
||||
if(g_c033_data & 0xc0) {
|
||||
printf("Writing test reg: %02x!\n",
|
||||
g_c033_data);
|
||||
/* set_halt(1); */
|
||||
}
|
||||
break;
|
||||
case 0x1: /* write protect reg */
|
||||
clk_printf("Writing clk wr_protect: %02x\n",
|
||||
g_c033_data);
|
||||
if(g_c033_data & 0x80) {
|
||||
printf("Stop, wr clk wr_prot: %02x\n",
|
||||
g_c033_data);
|
||||
/* set_halt(1); */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
halt_printf("Writing int reg: %02x with %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
}
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
default:
|
||||
halt_printf("clk mode: %d unknown!\n", g_clk_mode);
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
}
|
||||
g_clk_cur_time = (g_clk_cur_time & (~mask)) |
|
||||
((g_c033_data & 0xff) << (8 * g_clk_reg1));
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
case CLK_INTERNAL:
|
||||
if(read) {
|
||||
printf("Attempting to read internal reg %02x!\n",
|
||||
g_clk_reg1);
|
||||
} else {
|
||||
switch(g_clk_reg1) {
|
||||
case 0x0: /* test register */
|
||||
if(g_c033_data & 0xc0) {
|
||||
printf("Writing test reg: %02x!\n",
|
||||
g_c033_data);
|
||||
/* set_halt(1); */
|
||||
}
|
||||
break;
|
||||
case 0x1: /* write protect reg */
|
||||
clk_printf("Writing clk wr_protect: %02x\n",
|
||||
g_c033_data);
|
||||
if(g_c033_data & 0x80) {
|
||||
printf("Stop, wr clk wr_prot: %02x\n",
|
||||
g_c033_data);
|
||||
/* set_halt(1); */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
halt_printf("Writing int reg: %02x with %02x\n",
|
||||
g_clk_reg1, g_c033_data);
|
||||
}
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
default:
|
||||
halt_printf("clk mode: %d unknown!\n", g_clk_mode);
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
char g_compile_time[] = "Compiled: " __DATE__ " " __TIME__ ;
|
||||
char g_compile_time[] = "Compiled: " __DATE__ " " __TIME__;
|
||||
|
|
5646
src/config.c
5646
src/config.c
File diff suppressed because it is too large
Load Diff
521
src/debug.c
521
src/debug.c
|
@ -1,3 +1,10 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -25,7 +32,7 @@ extern const word32 disas_types[256];
|
|||
extern Engine_reg engine;
|
||||
extern int g_config_control_panel;
|
||||
extern int g_num_breakpoints;
|
||||
extern word32 g_breakpts[MAX_BREAK_POINTS];
|
||||
extern word32 g_breakpts[MAX_BREAK_POINTS];
|
||||
int g_dbg_enable_port = 0;
|
||||
int debug_pause = 0;
|
||||
int g_dbg_step = 0;
|
||||
|
@ -48,9 +55,9 @@ typedef enum {
|
|||
G_DBG_COMMAND_ADD_BRK = 8,
|
||||
G_DBG_COMMAND_DEL_BRK = 9,
|
||||
G_DBG_COMMAND_GET_BRK = 0xA,
|
||||
G_DBG_COMMAND_PAUSE = 0xB, // deprecated
|
||||
G_DBG_COMMAND_DEBUGGER = 0xC, // deprecated
|
||||
G_DBG_COMMAND_QUIT = 0xD, // deprecated
|
||||
G_DBG_COMMAND_PAUSE = 0xB, // deprecated
|
||||
G_DBG_COMMAND_DEBUGGER = 0xC, // deprecated
|
||||
G_DBG_COMMAND_QUIT = 0xD, // deprecated
|
||||
G_DBG_COMMAND_EMU_CMD = 0xE
|
||||
} G_DBG_COMMANDS;
|
||||
|
||||
|
@ -132,7 +139,7 @@ char buffer[BUFFER_SIZE];
|
|||
char tmp_buffer_4k[4097]; // adding +1 in case someone forgets \0
|
||||
char tmp_buffer2_4k[4097]; // adding +1 in case someone forgets \0
|
||||
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in addr;
|
||||
int timeout; // poll timeout in ms
|
||||
struct pollfd fds[200];
|
||||
int nfds = 0, current_size = 0, i, j;
|
||||
|
@ -141,20 +148,18 @@ int debugger_sd = -1; // this holds our socket file descriptor for the debugger,
|
|||
|
||||
|
||||
/* socket debug version */
|
||||
void
|
||||
do_go_debug()
|
||||
{
|
||||
void do_go_debug() {
|
||||
while (1) {
|
||||
if (g_dbg_step >= 0) {
|
||||
if (g_dbg_step == 1) {
|
||||
g_dbg_step = -1; // we are taking a step, so chill on the next round
|
||||
g_dbg_step = -1; // we are taking a step, so chill on the next round
|
||||
}
|
||||
g_config_control_panel = 0;
|
||||
clear_halt();
|
||||
|
||||
|
||||
glog("calling run_prog()");
|
||||
run_prog(); // also calls debug_server_poll()
|
||||
run_prog(); // also calls debug_server_poll()
|
||||
glog("left run_prog()");
|
||||
step_count++;
|
||||
|
||||
|
@ -190,7 +195,7 @@ void debug_push_message(G_DBG_COMMANDS msg_type, char *msg_ptr, int msg_len) {
|
|||
glogf("debug_push_message() GOT: %d", (int) msg_type);
|
||||
dbg_cmd_queue[dbg_cmd_queue_len].command = msg_type;
|
||||
memcpy(dbg_cmd_queue[dbg_cmd_queue_len].cdata, msg_ptr, msg_len); // stripping that first char
|
||||
dbg_cmd_queue[dbg_cmd_queue_len].cdata[msg_len+1] = '\0'; // terminator
|
||||
dbg_cmd_queue[dbg_cmd_queue_len].cdata[msg_len+1] = '\0'; // terminator
|
||||
dbg_cmd_queue_len++; // INC POINTER
|
||||
}
|
||||
|
||||
|
@ -281,8 +286,8 @@ void api_push_memack() {
|
|||
void api_push_cpu() {
|
||||
Engine_reg *eptr;
|
||||
eptr = &engine;
|
||||
int tmp_acc, tmp_x, tmp_y, tmp_psw;
|
||||
int kpc, direct_page, dbank, stack;
|
||||
int tmp_acc, tmp_x, tmp_y, tmp_psw;
|
||||
int kpc, direct_page, dbank, stack;
|
||||
|
||||
kpc = eptr->kpc;
|
||||
tmp_acc = eptr->acc;
|
||||
|
@ -293,9 +298,9 @@ void api_push_cpu() {
|
|||
tmp_y = eptr->yreg;
|
||||
tmp_psw = eptr->psr;
|
||||
|
||||
int size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),"{\"type\":\"cpu\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"A\":\"%04X\","\
|
||||
"\"X\":\"%04X\",\"Y\":\"%04X\",\"S\":\"%04X\",\"D\":\"%04X\",\"B\":\"%02X\",\"PSR\":\"%04X\"}}",
|
||||
kpc>>16, kpc & 0xffff ,tmp_acc,tmp_x,tmp_y,stack,direct_page,dbank, tmp_psw & 0xFFF);
|
||||
int size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),"{\"type\":\"cpu\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"A\":\"%04X\"," \
|
||||
"\"X\":\"%04X\",\"Y\":\"%04X\",\"S\":\"%04X\",\"D\":\"%04X\",\"B\":\"%02X\",\"PSR\":\"%04X\"}}",
|
||||
kpc>>16, kpc & 0xffff,tmp_acc,tmp_x,tmp_y,stack,direct_page,dbank, tmp_psw & 0xFFF);
|
||||
|
||||
char *msg = (char*)malloc(sizeof(char) * size);
|
||||
strcpy(msg,tmp_buffer_4k);
|
||||
|
@ -303,35 +308,35 @@ void api_push_cpu() {
|
|||
}
|
||||
|
||||
void api_push_brk() {
|
||||
int i;
|
||||
// build our json array of breakpoints
|
||||
tmp_buffer2_4k[0] = '\0'; // start with empty string
|
||||
char *str_ptr = tmp_buffer2_4k;
|
||||
for(i = 0; i < g_num_breakpoints; i++) {
|
||||
//printf("{\"bp:%02x: %06x\n", i, g_breakpts[i]);
|
||||
str_ptr += sprintf(str_ptr, "{\"trig\":\"addr\",\"match\":\"%06X\"}", g_breakpts[i]);
|
||||
if (i < g_num_breakpoints-1) {
|
||||
str_ptr += sprintf(str_ptr, ",");
|
||||
}
|
||||
}
|
||||
str_ptr = tmp_buffer2_4k; // reset pointer to beginning of string
|
||||
int i;
|
||||
// build our json array of breakpoints
|
||||
tmp_buffer2_4k[0] = '\0'; // start with empty string
|
||||
char *str_ptr = tmp_buffer2_4k;
|
||||
for(i = 0; i < g_num_breakpoints; i++) {
|
||||
//printf("{\"bp:%02x: %06x\n", i, g_breakpts[i]);
|
||||
str_ptr += sprintf(str_ptr, "{\"trig\":\"addr\",\"match\":\"%06X\"}", g_breakpts[i]);
|
||||
if (i < g_num_breakpoints-1) {
|
||||
str_ptr += sprintf(str_ptr, ",");
|
||||
}
|
||||
}
|
||||
str_ptr = tmp_buffer2_4k; // reset pointer to beginning of string
|
||||
|
||||
int size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),"{\"type\":\"brk\",\"data\":{\"breakpoints\":[%s]}}", str_ptr);
|
||||
int size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),"{\"type\":\"brk\",\"data\":{\"breakpoints\":[%s]}}", str_ptr);
|
||||
|
||||
char *msg = (char*)malloc(sizeof(char) * size);
|
||||
strcpy(msg,tmp_buffer_4k);
|
||||
push_api_msg(size, msg);
|
||||
char *msg = (char*)malloc(sizeof(char) * size);
|
||||
strcpy(msg,tmp_buffer_4k);
|
||||
push_api_msg(size, msg);
|
||||
}
|
||||
|
||||
|
||||
void api_push_stack() {
|
||||
Engine_reg *eptr;
|
||||
eptr = &engine;
|
||||
int kpc, stack;
|
||||
int kpc, stack;
|
||||
|
||||
kpc = eptr->kpc;
|
||||
stack = eptr->stack;
|
||||
word32 stack_loc = (kpc & 0xff0000) + (stack & 0xff00); // e.g. 0x00000100 (default) or 0x00FF0100 (GS Boot)
|
||||
word32 stack_loc = (kpc & 0xff0000) + (stack & 0xff00); // e.g. 0x00000100 (default) or 0x00FF0100 (GS Boot)
|
||||
|
||||
// build our json array of 256 stack values ($nn00-nnFF)
|
||||
char *str_ptr = tmp_buffer2_4k; // (1024B)
|
||||
|
@ -342,10 +347,10 @@ void api_push_stack() {
|
|||
str_ptr += sprintf(str_ptr, ",");
|
||||
}
|
||||
}
|
||||
str_ptr = tmp_buffer2_4k; // reset pointer to beginning of string
|
||||
str_ptr = tmp_buffer2_4k; // reset pointer to beginning of string
|
||||
|
||||
int size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),"{\"type\":\"stack\",\"data\":{\"loc\":\"%06X\",\"S\":\"%04X\",\"bytes\":[%s]}}",
|
||||
stack_loc,stack,str_ptr);
|
||||
stack_loc,stack,str_ptr);
|
||||
|
||||
char *msg = (char*)malloc(sizeof(char) * size);
|
||||
strcpy(msg,tmp_buffer_4k);
|
||||
|
@ -414,18 +419,18 @@ void api_push_disassembly_chain() {
|
|||
void api_push_dump(int bank, int start, int end) {
|
||||
char *post_str = "\"}}";
|
||||
int pre_size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),
|
||||
"{\"type\":\"mem\",\"data\":{\"bank\":\"%02X\",\"start\":\"%04X\",\"end\":\"%04X\",\"b64data\":\"",
|
||||
bank, start, end);
|
||||
"{\"type\":\"mem\",\"data\":{\"bank\":\"%02X\",\"start\":\"%04X\",\"end\":\"%04X\",\"b64data\":\"",
|
||||
bank, start, end);
|
||||
|
||||
int len = end - start + 1; // +1 for inclusive
|
||||
if (len <= 0x10000) {
|
||||
int b64len = b64encode_len(len);
|
||||
// get pointer to length of full message with data and json wrapper
|
||||
char *msg_json = (char*)malloc(sizeof(char) * (b64len + strlen(post_str) + pre_size + 1)); //? +1
|
||||
char *str_ptr = msg_json; // msg_json is our big malloced buffer
|
||||
char *msg_json = (char*)malloc(sizeof(char) * (b64len + strlen(post_str) + pre_size + 1)); //? +1
|
||||
char *str_ptr = msg_json; // msg_json is our big malloced buffer
|
||||
|
||||
strcat(str_ptr, tmp_buffer_4k); // prefix string from above
|
||||
str_ptr += strlen(tmp_buffer_4k); // move forward the ptr
|
||||
strcat(str_ptr, tmp_buffer_4k); // prefix string from above
|
||||
str_ptr += strlen(tmp_buffer_4k); // move forward the ptr
|
||||
// space to copy - can't figure out if i need to go through get_memory_c() or not
|
||||
char *memchunk = (char*)malloc(sizeof(char) * (len+1));
|
||||
for (int i = start; i <= end; i++) {
|
||||
|
@ -437,7 +442,7 @@ void api_push_dump(int bank, int start, int end) {
|
|||
b64encode(str_ptr, memchunk, len);
|
||||
|
||||
str_ptr = strcat(str_ptr, post_str); // "\"}}"
|
||||
push_api_msg(strlen(msg_json), msg_json); // don't free, de-queue will do that after writing to socket
|
||||
push_api_msg(strlen(msg_json), msg_json); // don't free, de-queue will do that after writing to socket
|
||||
//free(msg_json);
|
||||
free(memchunk);
|
||||
}
|
||||
|
@ -494,7 +499,7 @@ void event_did_step(int step_count) {
|
|||
api_push_stack();
|
||||
api_push_cpu();
|
||||
api_push_disassembly();
|
||||
if (step_count == 1 || g_dbg_step == -2) { // our first step?
|
||||
if (step_count == 1 || g_dbg_step == -2) { // our first step?
|
||||
api_push_disassembly_start();
|
||||
}
|
||||
api_write_socket();
|
||||
|
@ -523,7 +528,7 @@ void handle_set_bytes(int address, char *bytes_data) {
|
|||
while (sscanf(bytes_data, "%02x", &byte) == 1) {
|
||||
printf("$%02x <---- BYTE @ $%06X\n", byte, address );
|
||||
bytes_data += 2;
|
||||
address ++;
|
||||
address++;
|
||||
set_byte_at_address(address, byte & 0xFF);
|
||||
}
|
||||
}
|
||||
|
@ -536,15 +541,15 @@ void event_set_mem(char *str) {
|
|||
char *pch;
|
||||
pch = strtok (str," "); // split our memory sets on spaces
|
||||
while (pch != NULL) {
|
||||
sscanf(pch, "%06X", &address);
|
||||
sscanf(pch, "%06X", &address);
|
||||
|
||||
bytes_data = pch+6;
|
||||
printf("BytesData %s\n", bytes_data);
|
||||
bytes_data = pch+6;
|
||||
printf("BytesData %s\n", bytes_data);
|
||||
|
||||
// for each token go try to handle it
|
||||
handle_set_bytes(address, bytes_data);
|
||||
// for each token go try to handle it
|
||||
handle_set_bytes(address, bytes_data);
|
||||
|
||||
pch = strtok (NULL, " ");
|
||||
pch = strtok (NULL, " ");
|
||||
}
|
||||
api_push_memack(); // send ack
|
||||
api_write_socket();
|
||||
|
@ -586,13 +591,13 @@ void event_emu_cmd(char *str) {
|
|||
pch = strtok (str," ");
|
||||
while (pch != NULL)
|
||||
{
|
||||
cmd_char = pch[0];
|
||||
cmd_data = pch+1;
|
||||
if (cmd_data[0] == '\0') {
|
||||
cmd_data = NULL;
|
||||
}
|
||||
// for each token go try to handle it
|
||||
handle_emu_cmd(cmd_char, cmd_data);
|
||||
cmd_char = pch[0];
|
||||
cmd_data = pch+1;
|
||||
if (cmd_data[0] == '\0') {
|
||||
cmd_data = NULL;
|
||||
}
|
||||
// for each token go try to handle it
|
||||
handle_emu_cmd(cmd_char, cmd_data);
|
||||
|
||||
pch = strtok (NULL, " ");
|
||||
}
|
||||
|
@ -694,13 +699,13 @@ void event_set_cpu(char *str) {
|
|||
char * pch;
|
||||
pch = strtok (str," ");
|
||||
while (pch != NULL) {
|
||||
cmd_char = pch[0];
|
||||
cmd_data = pch+1;
|
||||
if (cmd_data[0] == '\0') {
|
||||
cmd_data = NULL;
|
||||
}
|
||||
// for each token go try to handle it
|
||||
handle_cpu_cmd(cmd_char, cmd_data);
|
||||
cmd_char = pch[0];
|
||||
cmd_data = pch+1;
|
||||
if (cmd_data[0] == '\0') {
|
||||
cmd_data = NULL;
|
||||
}
|
||||
// for each token go try to handle it
|
||||
handle_cpu_cmd(cmd_char, cmd_data);
|
||||
|
||||
pch = strtok (NULL, " ");
|
||||
}
|
||||
|
@ -791,7 +796,7 @@ void debug_setup_socket() {
|
|||
/*************************************************************/
|
||||
/* Initialize the pollfd structure */
|
||||
/*************************************************************/
|
||||
memset(fds, 0 , sizeof(fds));
|
||||
memset(fds, 0, sizeof(fds));
|
||||
|
||||
/*************************************************************/
|
||||
/* Set up the initial listening socket */
|
||||
|
@ -836,7 +841,7 @@ void api_write_socket() {
|
|||
// message_string is now built! we can send it.
|
||||
dbg_msg_queue_len = 0; // clear msg queue
|
||||
|
||||
writeStrToClient(debugger_sd, message_string); // ignores result
|
||||
writeStrToClient(debugger_sd, message_string); // ignores result
|
||||
free(message_string); // assuming it was all written :P
|
||||
}
|
||||
|
||||
|
@ -865,10 +870,10 @@ void write_array_next() {
|
|||
int writeDataToClient(int sckt, const void *data, int datalen) {
|
||||
const char *pdata = (const char*) data;
|
||||
|
||||
while (datalen > 0){
|
||||
while (datalen > 0) {
|
||||
int numSent = send(sckt, pdata, datalen, 0);
|
||||
if (numSent <= 0){
|
||||
if (numSent == 0){
|
||||
if (numSent <= 0) {
|
||||
if (numSent == 0) {
|
||||
printf("The client was not written to: disconnected\n");
|
||||
} else {
|
||||
perror("The client was not written to");
|
||||
|
@ -1051,10 +1056,10 @@ void debug_server_poll() {
|
|||
char *mesg_ptr = buffer;
|
||||
char *split_ptr = strchr(mesg_ptr, '\n');
|
||||
|
||||
int mesg_len = len-1; // stripping that first char
|
||||
int mesg_len = len-1; // stripping that first char
|
||||
if(split_ptr) {
|
||||
int index = split_ptr - buffer;
|
||||
mesg_len = index - 1; // stripping that first char
|
||||
mesg_len = index - 1; // stripping that first char
|
||||
}
|
||||
int debug_echo = FALSE;
|
||||
while (mesg_ptr < buffer + len - 1) {
|
||||
|
@ -1095,13 +1100,13 @@ void debug_server_poll() {
|
|||
debug_push_message(G_DBG_COMMAND_GET_BRK, mesg_ptr+1, mesg_len);
|
||||
break;
|
||||
|
||||
case 'b': // DEPRECATED
|
||||
case 'b': // DEPRECATED
|
||||
debug_push_message(G_DBG_COMMAND_PAUSE, mesg_ptr+1, mesg_len);
|
||||
break;
|
||||
case 'c': // DEPRECATED
|
||||
case 'c': // DEPRECATED
|
||||
debug_push_message(G_DBG_COMMAND_DEBUGGER, mesg_ptr+1, mesg_len);
|
||||
break;
|
||||
case 'd': // DEPRECATED ????
|
||||
case 'd': // DEPRECATED ????
|
||||
debug_push_message(G_DBG_COMMAND_QUIT, mesg_ptr+1, mesg_len);
|
||||
break;
|
||||
|
||||
|
@ -1119,11 +1124,11 @@ void debug_server_poll() {
|
|||
// @TODO probably send error response
|
||||
}
|
||||
|
||||
mesg_ptr += mesg_len + 2; // +1 for command char and +1 for '\n'
|
||||
mesg_ptr += mesg_len + 2; // +1 for command char and +1 for '\n'
|
||||
split_ptr = strchr(mesg_ptr, '\n');
|
||||
if(split_ptr) {
|
||||
int index = split_ptr - mesg_ptr;
|
||||
mesg_len = index - 1; // stripping that first char
|
||||
mesg_len = index - 1; // stripping that first char
|
||||
}
|
||||
}
|
||||
/*****************************************************/
|
||||
|
@ -1183,7 +1188,7 @@ void debug_server_poll() {
|
|||
/*************************************************************/
|
||||
for (i = 0; i < nfds; i++) {
|
||||
if(fds[i].fd >= 0)
|
||||
close(fds[i].fd);
|
||||
close(fds[i].fd);
|
||||
}
|
||||
nfds = 0;
|
||||
}
|
||||
|
@ -1196,12 +1201,12 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
|
|||
|
||||
|
||||
const char *out;
|
||||
int args, type;
|
||||
int opcode;
|
||||
word32 val;
|
||||
word32 oldkpc;
|
||||
word32 dtype;
|
||||
int signed_val;
|
||||
int args, type;
|
||||
int opcode;
|
||||
word32 val;
|
||||
word32 oldkpc;
|
||||
word32 dtype;
|
||||
int signed_val;
|
||||
|
||||
oldkpc = kpc;
|
||||
if(op_provided) {
|
||||
|
@ -1228,33 +1233,33 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
|
|||
val = -1;
|
||||
switch(args) {
|
||||
case 0:
|
||||
val = 0;
|
||||
break;
|
||||
val = 0;
|
||||
break;
|
||||
case 1:
|
||||
if(op_provided) {
|
||||
val = instr & 0xff;
|
||||
} else {
|
||||
val = get_memory_c(kpc, 0);
|
||||
}
|
||||
break;
|
||||
if(op_provided) {
|
||||
val = instr & 0xff;
|
||||
} else {
|
||||
val = get_memory_c(kpc, 0);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(op_provided) {
|
||||
val = instr & 0xffff;
|
||||
} else {
|
||||
val = get_memory16_c(kpc, 0);
|
||||
}
|
||||
break;
|
||||
if(op_provided) {
|
||||
val = instr & 0xffff;
|
||||
} else {
|
||||
val = get_memory16_c(kpc, 0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(op_provided) {
|
||||
val = instr & 0xffffff;
|
||||
} else {
|
||||
val = get_memory24_c(kpc, 0);
|
||||
}
|
||||
break;
|
||||
if(op_provided) {
|
||||
val = instr & 0xffffff;
|
||||
} else {
|
||||
val = get_memory24_c(kpc, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "args out of range: %d, opcode: %08x\n",
|
||||
args, opcode);
|
||||
break;
|
||||
fprintf(stderr, "args out of range: %d, opcode: %08x\n",
|
||||
args, opcode);
|
||||
break;
|
||||
}
|
||||
kpc += args;
|
||||
|
||||
|
@ -1264,171 +1269,171 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
|
|||
|
||||
switch(type) {
|
||||
case ABS:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x",out,val);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x",out,val);
|
||||
break;
|
||||
case ABSX:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x,X",out,val);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x,X",out,val);
|
||||
break;
|
||||
case ABSY:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x,Y",out,val);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x,Y",out,val);
|
||||
break;
|
||||
case ABSLONG:
|
||||
if(args != 3) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%06x",out,val);
|
||||
break;
|
||||
if(args != 3) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%06x",out,val);
|
||||
break;
|
||||
case ABSIND:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%04x)",out,val);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%04x)",out,val);
|
||||
break;
|
||||
case ABSXIND:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%04x,X)",out,val);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%04x,X)",out,val);
|
||||
break;
|
||||
case IMPLY:
|
||||
if(args != 0) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s",out);
|
||||
break;
|
||||
if(args != 0) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s",out);
|
||||
break;
|
||||
case ACCUM:
|
||||
if(args != 0) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s",out);
|
||||
break;
|
||||
if(args != 0) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s",out);
|
||||
break;
|
||||
case IMMED:
|
||||
if(args == 1) {
|
||||
sprintf(buf_disasm,"%s #$%02x",out,val);
|
||||
} else if(args == 2) {
|
||||
sprintf(buf_disasm,"%s #$%04x",out,val);
|
||||
} else {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
break;
|
||||
if(args == 1) {
|
||||
sprintf(buf_disasm,"%s #$%02x",out,val);
|
||||
} else if(args == 2) {
|
||||
sprintf(buf_disasm,"%s #$%04x",out,val);
|
||||
} else {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
break;
|
||||
case JUST8:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x",out,val);
|
||||
break;
|
||||
case DLOC:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x",out,val);
|
||||
break;
|
||||
case DLOCX:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,X",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,X",out,val);
|
||||
break;
|
||||
case DLOCY:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,Y",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,Y",out,val);
|
||||
break;
|
||||
case LONG:
|
||||
if(args != 3) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%06x",out,val);
|
||||
break;
|
||||
if(args != 3) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%06x",out,val);
|
||||
break;
|
||||
case LONGX:
|
||||
if(args != 3) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%06x,X",out,val);
|
||||
break;
|
||||
if(args != 3) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%06x,X",out,val);
|
||||
break;
|
||||
case DLOCIND:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x)",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x)",out,val);
|
||||
break;
|
||||
case DLOCINDY:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x),Y",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x),Y",out,val);
|
||||
break;
|
||||
case DLOCXIND:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x,X)",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x,X)",out,val);
|
||||
break;
|
||||
case DLOCBRAK:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s [$%02x]",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s [$%02x]",out,val);
|
||||
break;
|
||||
case DLOCBRAKY:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s [$%02x],y",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s [$%02x],y",out,val);
|
||||
break;
|
||||
case DISP8:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
signed_val = (signed char)val;
|
||||
sprintf(buf_disasm,"%s $%04x",out,
|
||||
(word32)(kpc+(signed_val)) & 0xffff);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
signed_val = (signed char)val;
|
||||
sprintf(buf_disasm,"%s $%04x",out,
|
||||
(word32)(kpc+(signed_val)) & 0xffff);
|
||||
break;
|
||||
case DISP8S:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,S",out,(word32)(byte)(val));
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,S",out,(word32)(byte)(val));
|
||||
break;
|
||||
case DISP8SINDY:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x,S),Y",out,(word32)(byte)(val));
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s ($%02x,S),Y",out,(word32)(byte)(val));
|
||||
break;
|
||||
case DISP16:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x", out,
|
||||
(word32)(kpc+(signed)(word16)(val)) & 0xffff);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%04x", out,
|
||||
(word32)(kpc+(signed)(word16)(val)) & 0xffff);
|
||||
break;
|
||||
case MVPMVN:
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,$%02x",out,val&0xff,val>>8);
|
||||
break;
|
||||
if(args != 2) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s $%02x,$%02x",out,val&0xff,val>>8);
|
||||
break;
|
||||
case SEPVAL:
|
||||
case REPVAL:
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s #$%02x",out,val);
|
||||
break;
|
||||
if(args != 1) {
|
||||
printf("arg # mismatch for opcode %x\n", opcode);
|
||||
}
|
||||
sprintf(buf_disasm,"%s #$%02x",out,val);
|
||||
break;
|
||||
default:
|
||||
printf("argument type: %d unexpected\n", type);
|
||||
break;
|
||||
printf("argument type: %d unexpected\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1437,26 +1442,26 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
|
|||
opcode = (operand >> 24) & 0xff;
|
||||
switch (args+1) {
|
||||
case 1:
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\"]", opcode);
|
||||
break;
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\"]", opcode);
|
||||
break;
|
||||
case 2:
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\"]", opcode, instr & 0xff);
|
||||
break;
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\"]", opcode, instr & 0xff);
|
||||
break;
|
||||
case 3:
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8);
|
||||
break;
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8);
|
||||
break;
|
||||
case 4:
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8, (instr & 0xff0000) >> 16);
|
||||
break;
|
||||
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8, (instr & 0xff0000) >> 16);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// @TODO: FIX!!! NEEDS REAL BUFFER SIZE, note magic 1024
|
||||
snprintf(buf, 1024,"{\"type\":\"dis\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"bytes\":%s,"\
|
||||
"\"disasm\":\"%s\",\"chain\":\"%d\"}}",
|
||||
oldkpc>>16, oldkpc & 0xffff ,buf_instructions, buf_disasm, chain);
|
||||
snprintf(buf, 1024,"{\"type\":\"dis\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"bytes\":%s," \
|
||||
"\"disasm\":\"%s\",\"chain\":\"%d\"}}",
|
||||
oldkpc>>16, oldkpc & 0xffff,buf_instructions, buf_disasm, chain);
|
||||
return(args+1);
|
||||
}
|
||||
|
||||
|
@ -1488,7 +1493,7 @@ int b64encode(char *encoded, const char *string, int len) {
|
|||
*p++ = '=';
|
||||
} else {
|
||||
*p++ = b64chars[((string[i] & 0x3) << 4) |
|
||||
((int) (string[i + 1] & 0xF0) >> 4)];
|
||||
((int) (string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = b64chars[((string[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
|
|
350
src/defc.h
350
src/defc.h
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defcomm.h"
|
||||
|
||||
|
@ -12,8 +12,8 @@
|
|||
#include <stdio.h>
|
||||
extern "C" int outputInfo(const char* format,...);
|
||||
extern "C" int fOutputInfo(FILE*,const char* format,...);
|
||||
#define printf outputInfo
|
||||
#define fprintf fOutputInfo
|
||||
#define printf outputInfo
|
||||
#define fprintf fOutputInfo
|
||||
#endif
|
||||
|
||||
#define STRUCT(a) typedef struct _ ## a a; struct _ ## a
|
||||
|
@ -30,31 +30,31 @@ typedef unsigned long long word64;
|
|||
void U_STACK_TRACE();
|
||||
|
||||
/* 28MHz crystal, plus every 65th 1MHz cycle is stretched 140ns */
|
||||
#define CYCS_28_MHZ (28636360)
|
||||
#define DCYCS_28_MHZ (1.0*CYCS_28_MHZ)
|
||||
#define CYCS_3_5_MHZ (CYCS_28_MHZ/8)
|
||||
#define DCYCS_1_MHZ ((DCYCS_28_MHZ/28.0)*(65.0*7/(65.0*7+1.0)))
|
||||
#define CYCS_1_MHZ ((int)DCYCS_1_MHZ)
|
||||
#define CYCS_28_MHZ (28636360)
|
||||
#define DCYCS_28_MHZ (1.0*CYCS_28_MHZ)
|
||||
#define CYCS_3_5_MHZ (CYCS_28_MHZ/8)
|
||||
#define DCYCS_1_MHZ ((DCYCS_28_MHZ/28.0)*(65.0*7/(65.0*7+1.0)))
|
||||
#define CYCS_1_MHZ ((int)DCYCS_1_MHZ)
|
||||
|
||||
/* #define DCYCS_IN_16MS_RAW (DCYCS_1_MHZ / 60.0) */
|
||||
#define DCYCS_IN_16MS_RAW (262.0 * 65.0)
|
||||
#define DCYCS_IN_16MS_RAW (262.0 * 65.0)
|
||||
/* Use precisely 17030 instead of forcing 60 Hz since this is the number of */
|
||||
/* 1MHz cycles per screen */
|
||||
#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW))
|
||||
#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS))
|
||||
#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW))
|
||||
#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS))
|
||||
|
||||
#ifdef GSPLUS_LITTLE_ENDIAN
|
||||
// @todo: look at using <byteswap.h> for fastest platform implementations
|
||||
# define BIGEND(a) ((((a) >> 24) & 0xff) + \
|
||||
(((a) >> 8) & 0xff00) + \
|
||||
(((a) << 8) & 0xff0000) + \
|
||||
(((a) << 24) & 0xff000000))
|
||||
# define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00))
|
||||
# define GET_BE_WORD32(a) (BIGEND(a))
|
||||
# define BIGEND(a) ((((a) >> 24) & 0xff) + \
|
||||
(((a) >> 8) & 0xff00) + \
|
||||
(((a) << 8) & 0xff0000) + \
|
||||
(((a) << 24) & 0xff000000))
|
||||
# define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00))
|
||||
# define GET_BE_WORD32(a) (BIGEND(a))
|
||||
#else
|
||||
# define BIGEND(a) (a)
|
||||
# define GET_BE_WORD16(a) (a)
|
||||
# define GET_BE_WORD32(a) (a)
|
||||
# define BIGEND(a) (a)
|
||||
# define GET_BE_WORD16(a) (a)
|
||||
# define GET_BE_WORD32(a) (a)
|
||||
#endif
|
||||
|
||||
#define MAXNUM_HEX_PER_LINE 32
|
||||
|
@ -63,7 +63,7 @@ void U_STACK_TRACE();
|
|||
# include <libc.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(UNDER_CE) // OG
|
||||
#if !defined(_WIN32) && !defined(UNDER_CE) // OG
|
||||
# include <unistd.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/wait.h>
|
||||
|
@ -77,7 +77,7 @@ void U_STACK_TRACE();
|
|||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef UNDER_CE // OG CE SPecific
|
||||
#ifndef UNDER_CE // OG CE SPecific
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -93,24 +93,24 @@ extern int open(const char* name,int,...);
|
|||
extern int read(int,char*,int);
|
||||
extern int close(int);
|
||||
extern int write( int fd, const void *buffer, unsigned int count );
|
||||
extern int lseek(int,int,int);
|
||||
extern int lseek(int,int,int);
|
||||
struct stat { int st_size; };
|
||||
extern int stat(const char* name, struct stat*);
|
||||
extern int fstat(int, struct stat*);
|
||||
#define O_RDWR 1
|
||||
#define O_BINARY 2
|
||||
#define O_RDONLY 4
|
||||
#define O_WRONLY 8
|
||||
#define O_CREAT 16
|
||||
#define O_TRUNC 32
|
||||
#define EAGAIN 11
|
||||
#define EINTR 4
|
||||
#define O_RDWR 1
|
||||
#define O_BINARY 2
|
||||
#define O_RDONLY 4
|
||||
#define O_WRONLY 8
|
||||
#define O_CREAT 16
|
||||
#define O_TRUNC 32
|
||||
#define EAGAIN 11
|
||||
#define EINTR 4
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HPUX
|
||||
# include <machine/inline.h> /* for GET_ITIMER */
|
||||
# include <machine/inline.h> /* for GET_ITIMER */
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
|
@ -119,232 +119,232 @@ extern int fstat(int, struct stat*);
|
|||
|
||||
#ifndef O_BINARY
|
||||
/* work around some Windows junk */
|
||||
# define O_BINARY 0
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
STRUCT(Pc_log) {
|
||||
double dcycs;
|
||||
word32 dbank_kpc;
|
||||
word32 instr;
|
||||
word32 psr_acc;
|
||||
word32 xreg_yreg;
|
||||
word32 stack_direct;
|
||||
word32 pad;
|
||||
double dcycs;
|
||||
word32 dbank_kpc;
|
||||
word32 instr;
|
||||
word32 psr_acc;
|
||||
word32 xreg_yreg;
|
||||
word32 stack_direct;
|
||||
word32 pad;
|
||||
};
|
||||
|
||||
STRUCT(Data_log) {
|
||||
double dcycs;
|
||||
word32 addr;
|
||||
word32 val;
|
||||
word32 size;
|
||||
double dcycs;
|
||||
word32 addr;
|
||||
word32 val;
|
||||
word32 size;
|
||||
};
|
||||
|
||||
STRUCT(Event) {
|
||||
double dcycs;
|
||||
int type;
|
||||
Event *next;
|
||||
double dcycs;
|
||||
int type;
|
||||
Event *next;
|
||||
};
|
||||
|
||||
STRUCT(Fplus) {
|
||||
double plus_1;
|
||||
double plus_2;
|
||||
double plus_3;
|
||||
double plus_x_minus_1;
|
||||
double plus_1;
|
||||
double plus_2;
|
||||
double plus_3;
|
||||
double plus_x_minus_1;
|
||||
};
|
||||
|
||||
STRUCT(Engine_reg) {
|
||||
double fcycles;
|
||||
word32 kpc;
|
||||
word32 acc;
|
||||
double fcycles;
|
||||
word32 kpc;
|
||||
word32 acc;
|
||||
|
||||
word32 xreg;
|
||||
word32 yreg;
|
||||
word32 xreg;
|
||||
word32 yreg;
|
||||
|
||||
word32 stack;
|
||||
word32 dbank;
|
||||
word32 stack;
|
||||
word32 dbank;
|
||||
|
||||
word32 direct;
|
||||
word32 psr;
|
||||
Fplus *fplus_ptr;
|
||||
word32 direct;
|
||||
word32 psr;
|
||||
Fplus *fplus_ptr;
|
||||
};
|
||||
|
||||
STRUCT(Kimage) {
|
||||
void *dev_handle;
|
||||
void *dev_handle2;
|
||||
byte *data_ptr;
|
||||
int width_req;
|
||||
int width_act;
|
||||
int height;
|
||||
int depth;
|
||||
int mdepth;
|
||||
int aux_info;
|
||||
void *dev_handle;
|
||||
void *dev_handle2;
|
||||
byte *data_ptr;
|
||||
int width_req;
|
||||
int width_act;
|
||||
int height;
|
||||
int depth;
|
||||
int mdepth;
|
||||
int aux_info;
|
||||
};
|
||||
|
||||
typedef byte *Pg_info;
|
||||
STRUCT(Page_info) {
|
||||
Pg_info rd_wr;
|
||||
Pg_info rd_wr;
|
||||
};
|
||||
|
||||
STRUCT(Cfg_menu) {
|
||||
const char *str;
|
||||
void *ptr;
|
||||
const char *name_str;
|
||||
void *defptr;
|
||||
int cfgtype;
|
||||
const char *str;
|
||||
void *ptr;
|
||||
const char *name_str;
|
||||
void *defptr;
|
||||
int cfgtype;
|
||||
};
|
||||
|
||||
STRUCT(Cfg_dirent) {
|
||||
char *name;
|
||||
int is_dir;
|
||||
int size;
|
||||
int image_start;
|
||||
int part_num;
|
||||
char *name;
|
||||
int is_dir;
|
||||
int size;
|
||||
int image_start;
|
||||
int part_num;
|
||||
};
|
||||
|
||||
STRUCT(Cfg_listhdr) {
|
||||
Cfg_dirent *direntptr;
|
||||
int max;
|
||||
int last;
|
||||
int invalid;
|
||||
Cfg_dirent *direntptr;
|
||||
int max;
|
||||
int last;
|
||||
int invalid;
|
||||
|
||||
int curent;
|
||||
int topent;
|
||||
int curent;
|
||||
int topent;
|
||||
|
||||
int num_to_show;
|
||||
int num_to_show;
|
||||
};
|
||||
|
||||
STRUCT(Emustate_intlist) {
|
||||
const char *str;
|
||||
int *iptr;
|
||||
const char *str;
|
||||
int *iptr;
|
||||
};
|
||||
|
||||
STRUCT(Emustate_dbllist) {
|
||||
const char *str;
|
||||
double *dptr;
|
||||
const char *str;
|
||||
double *dptr;
|
||||
};
|
||||
|
||||
STRUCT(Emustate_word32list) {
|
||||
const char *str;
|
||||
word32 *wptr;
|
||||
const char *str;
|
||||
word32 *wptr;
|
||||
};
|
||||
|
||||
#ifdef __LP64__
|
||||
# define PTR2WORD(a) ((unsigned long)(a))
|
||||
# define PTR2WORD(a) ((unsigned long)(a))
|
||||
#else
|
||||
# define PTR2WORD(a) ((unsigned int)(a))
|
||||
# define PTR2WORD(a) ((unsigned int)(a))
|
||||
#endif
|
||||
|
||||
|
||||
#define ALTZP (g_c068_statereg & 0x80)
|
||||
#define ALTZP (g_c068_statereg & 0x80)
|
||||
/* #define PAGE2 (g_c068_statereg & 0x40) */
|
||||
#define RAMRD (g_c068_statereg & 0x20)
|
||||
#define RAMWRT (g_c068_statereg & 0x10)
|
||||
#define RDROM (g_c068_statereg & 0x08)
|
||||
#define LCBANK2 (g_c068_statereg & 0x04)
|
||||
#define ROMB (g_c068_statereg & 0x02)
|
||||
#define INTCX (g_c068_statereg & 0x01)
|
||||
#define RAMRD (g_c068_statereg & 0x20)
|
||||
#define RAMWRT (g_c068_statereg & 0x10)
|
||||
#define RDROM (g_c068_statereg & 0x08)
|
||||
#define LCBANK2 (g_c068_statereg & 0x04)
|
||||
#define ROMB (g_c068_statereg & 0x02)
|
||||
#define INTCX (g_c068_statereg & 0x01)
|
||||
|
||||
#define C041_EN_25SEC_INTS 0x10
|
||||
#define C041_EN_VBL_INTS 0x08
|
||||
#define C041_EN_SWITCH_INTS 0x04
|
||||
#define C041_EN_MOVE_INTS 0x02
|
||||
#define C041_EN_MOUSE 0x01
|
||||
#define C041_EN_25SEC_INTS 0x10
|
||||
#define C041_EN_VBL_INTS 0x08
|
||||
#define C041_EN_SWITCH_INTS 0x04
|
||||
#define C041_EN_MOVE_INTS 0x02
|
||||
#define C041_EN_MOUSE 0x01
|
||||
|
||||
/* WARNING: SCC1 and SCC0 interrupts must be in this order for scc.c */
|
||||
/* This order matches the SCC hardware */
|
||||
#define IRQ_PENDING_SCC1_ZEROCNT 0x00001
|
||||
#define IRQ_PENDING_SCC1_TX 0x00002
|
||||
#define IRQ_PENDING_SCC1_RX 0x00004
|
||||
#define IRQ_PENDING_SCC0_ZEROCNT 0x00008
|
||||
#define IRQ_PENDING_SCC0_TX 0x00010
|
||||
#define IRQ_PENDING_SCC0_RX 0x00020
|
||||
#define IRQ_PENDING_C023_SCAN 0x00100
|
||||
#define IRQ_PENDING_C023_1SEC 0x00200
|
||||
#define IRQ_PENDING_C046_25SEC 0x00400
|
||||
#define IRQ_PENDING_C046_VBL 0x00800
|
||||
#define IRQ_PENDING_ADB_KBD_SRQ 0x01000
|
||||
#define IRQ_PENDING_ADB_DATA 0x02000
|
||||
#define IRQ_PENDING_ADB_MOUSE 0x04000
|
||||
#define IRQ_PENDING_DOC 0x08000
|
||||
#define IRQ_PENDING_SCC1_ZEROCNT 0x00001
|
||||
#define IRQ_PENDING_SCC1_TX 0x00002
|
||||
#define IRQ_PENDING_SCC1_RX 0x00004
|
||||
#define IRQ_PENDING_SCC0_ZEROCNT 0x00008
|
||||
#define IRQ_PENDING_SCC0_TX 0x00010
|
||||
#define IRQ_PENDING_SCC0_RX 0x00020
|
||||
#define IRQ_PENDING_C023_SCAN 0x00100
|
||||
#define IRQ_PENDING_C023_1SEC 0x00200
|
||||
#define IRQ_PENDING_C046_25SEC 0x00400
|
||||
#define IRQ_PENDING_C046_VBL 0x00800
|
||||
#define IRQ_PENDING_ADB_KBD_SRQ 0x01000
|
||||
#define IRQ_PENDING_ADB_DATA 0x02000
|
||||
#define IRQ_PENDING_ADB_MOUSE 0x04000
|
||||
#define IRQ_PENDING_DOC 0x08000
|
||||
|
||||
|
||||
#define EXTRU(val, pos, len) \
|
||||
( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \
|
||||
(((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) )
|
||||
#define EXTRU(val, pos, len) \
|
||||
( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \
|
||||
(((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) )
|
||||
|
||||
#define DEP1(val, pos, old_val) \
|
||||
(((old_val) & ~(1 << (31 - (pos))) ) | \
|
||||
( ((val) & 1) << (31 - (pos))) )
|
||||
#define DEP1(val, pos, old_val) \
|
||||
(((old_val) & ~(1 << (31 - (pos))) ) | \
|
||||
( ((val) & 1) << (31 - (pos))) )
|
||||
|
||||
#define set_halt(val) \
|
||||
if(val) { set_halt_act(val); }
|
||||
if(val) { set_halt_act(val); }
|
||||
|
||||
#define clear_halt() \
|
||||
clr_halt_act()
|
||||
clr_halt_act()
|
||||
|
||||
#define GET_PAGE_INFO_RD(page) \
|
||||
(page_info_rd_wr[page].rd_wr)
|
||||
(page_info_rd_wr[page].rd_wr)
|
||||
|
||||
#define GET_PAGE_INFO_WR(page) \
|
||||
(page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr)
|
||||
(page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr)
|
||||
|
||||
#define SET_PAGE_INFO_RD(page,val) \
|
||||
;page_info_rd_wr[page].rd_wr = (Pg_info)val;
|
||||
; page_info_rd_wr[page].rd_wr = (Pg_info)val;
|
||||
|
||||
#define SET_PAGE_INFO_WR(page,val) \
|
||||
;page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = \
|
||||
(Pg_info)val;
|
||||
; page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = \
|
||||
(Pg_info)val;
|
||||
|
||||
#define VERBOSE_DISK 0x001
|
||||
#define VERBOSE_IRQ 0x002
|
||||
#define VERBOSE_CLK 0x004
|
||||
#define VERBOSE_SHADOW 0x008
|
||||
#define VERBOSE_IWM 0x010
|
||||
#define VERBOSE_DOC 0x020
|
||||
#define VERBOSE_ADB 0x040
|
||||
#define VERBOSE_SCC 0x080
|
||||
#define VERBOSE_TEST 0x100
|
||||
#define VERBOSE_VIDEO 0x200
|
||||
#define VERBOSE_MAC 0x400
|
||||
#define VERBOSE_DISK 0x001
|
||||
#define VERBOSE_IRQ 0x002
|
||||
#define VERBOSE_CLK 0x004
|
||||
#define VERBOSE_SHADOW 0x008
|
||||
#define VERBOSE_IWM 0x010
|
||||
#define VERBOSE_DOC 0x020
|
||||
#define VERBOSE_ADB 0x040
|
||||
#define VERBOSE_SCC 0x080
|
||||
#define VERBOSE_TEST 0x100
|
||||
#define VERBOSE_VIDEO 0x200
|
||||
#define VERBOSE_MAC 0x400
|
||||
|
||||
#ifdef NO_VERB
|
||||
# define DO_VERBOSE 0
|
||||
# define DO_VERBOSE 0
|
||||
#else
|
||||
# define DO_VERBOSE 1
|
||||
# define DO_VERBOSE 1
|
||||
#endif
|
||||
|
||||
#define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf
|
||||
#define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf
|
||||
#define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf
|
||||
#define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf
|
||||
#define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf
|
||||
#define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf
|
||||
#define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf
|
||||
#define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf
|
||||
#define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf
|
||||
#define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf
|
||||
#define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf
|
||||
#define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf
|
||||
#define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf
|
||||
#define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf
|
||||
#define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf
|
||||
#define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf
|
||||
#define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf
|
||||
#define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf
|
||||
#define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf
|
||||
#define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf
|
||||
#define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf
|
||||
#define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf
|
||||
|
||||
|
||||
#define HALT_ON_SCAN_INT 0x001
|
||||
#define HALT_ON_IRQ 0x002
|
||||
#define HALT_ON_SHADOW_REG 0x004
|
||||
#define HALT_ON_C70D_WRITES 0x008
|
||||
#define HALT_ON_SCAN_INT 0x001
|
||||
#define HALT_ON_IRQ 0x002
|
||||
#define HALT_ON_SHADOW_REG 0x004
|
||||
#define HALT_ON_C70D_WRITES 0x008
|
||||
|
||||
#define HALT_ON(a, msg) \
|
||||
if(Halt_on & a) { \
|
||||
halt_printf(msg); \
|
||||
}
|
||||
#define HALT_ON(a, msg) \
|
||||
if(Halt_on & a) { \
|
||||
halt_printf(msg); \
|
||||
}
|
||||
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) (((a) < (b)) ? (b) : (a))
|
||||
# define MAX(a,b) (((a) < (b)) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#define GET_ITIMER(dest) dest = get_itimer();
|
||||
#define GET_ITIMER(dest) dest = get_itimer();
|
||||
|
||||
#include "iwm.h"
|
||||
#include "protos.h"
|
||||
|
@ -353,7 +353,7 @@ STRUCT(Emustate_word32list) {
|
|||
#define JOYSTICK_TYPE_MOUSE 1
|
||||
#define JOYSTICK_TYPE_NATIVE_1 2
|
||||
#define JOYSTICK_TYPE_NATIVE_2 3
|
||||
#define JOYSTICK_TYPE_NONE 4 // OG Added Joystick None
|
||||
#define JOYSTICK_TYPE_NONE 4 // OG Added Joystick None
|
||||
#define NB_JOYSTICK_TYPE 5
|
||||
|
||||
// starting window x/y position if Undefined
|
||||
|
|
1641
src/engine_c.c
1641
src/engine_c.c
File diff suppressed because it is too large
Load Diff
852
src/fbdriver.c
852
src/fbdriver.c
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/*
|
||||
* fbdriver - Linux fullscreen framebuffer graphics driver
|
||||
|
@ -27,11 +27,11 @@ extern word32 g_palette_8to1624[256];
|
|||
extern word32 g_a2palette_8to1624[256];
|
||||
extern word32 g_a2_screen_buffer_changed;
|
||||
extern word32 g_c025_val;
|
||||
#define SHIFT_DOWN ( (g_c025_val & 0x01) )
|
||||
#define CTRL_DOWN ( (g_c025_val & 0x02) )
|
||||
#define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) )
|
||||
#define OPTION_DOWN ( (g_c025_val & 0x40) )
|
||||
#define CMD_DOWN ( (g_c025_val & 0x80) )
|
||||
#define SHIFT_DOWN ( (g_c025_val & 0x01) )
|
||||
#define CTRL_DOWN ( (g_c025_val & 0x02) )
|
||||
#define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) )
|
||||
#define OPTION_DOWN ( (g_c025_val & 0x40) )
|
||||
#define CMD_DOWN ( (g_c025_val & 0x80) )
|
||||
extern int g_video_act_margin_left;
|
||||
extern int g_video_act_margin_right;
|
||||
extern int g_video_act_margin_top;
|
||||
|
@ -53,491 +53,469 @@ extern int g_green_right_shift;
|
|||
extern int g_blue_right_shift;
|
||||
extern Kimage g_mainwin_kimage;
|
||||
|
||||
int keycode_to_a2code[128] =
|
||||
int keycode_to_a2code[128] =
|
||||
{
|
||||
-1, // KEY_RESERVED
|
||||
0x35, // KEY_ESC
|
||||
0x12, // KEY_1
|
||||
0x13, // KEY_2
|
||||
0x14, // KEY_3
|
||||
0x15, // KEY_4
|
||||
0x17, // KEY_5
|
||||
0x16, // KEY_6
|
||||
0x1A, // KEY_7
|
||||
0x1C, // KEY_8
|
||||
0x19, // KEY_9
|
||||
0x1D, // KEY_0
|
||||
0x1B, // KEY_MINUS
|
||||
0x18, // KEY_EQUAL
|
||||
0x3B, // KEY_BACKSPACE0
|
||||
0x30, // KEY_TAB
|
||||
0x0C, // KEY_Q
|
||||
0x0D, // KEY_W
|
||||
0x0E, // KEY_E
|
||||
0x0F, // KEY_R
|
||||
0x11, // KEY_T
|
||||
0x10, // KEY_Y
|
||||
0x20, // KEY_U
|
||||
0x22, // KEY_I
|
||||
0x1F, // KEY_O
|
||||
0x23, // KEY_P
|
||||
0x21, // KEY_LEFTBRACE
|
||||
0x1E, // KEY_RIGHTBRACE
|
||||
0x24, // KEY_ENTER
|
||||
0x36, // KEY_LEFTCTRL
|
||||
0x00, // KEY_A
|
||||
0x01, // KEY_S
|
||||
0x02, // KEY_D
|
||||
0x03, // KEY_F
|
||||
0x05, // KEY_G
|
||||
0x04, // KEY_H
|
||||
0x26, // KEY_J
|
||||
0x28, // KEY_K
|
||||
0x25, // KEY_L
|
||||
0x29, // KEY_SEMICOLON
|
||||
0x27, // KEY_APOSTROPHE
|
||||
0x32, // KEY_GRAVE
|
||||
0x38, // KEY_LEFTSHIFT
|
||||
0x2A, // KEY_BACKSLASH
|
||||
0x06, // KEY_Z
|
||||
0x07, // KEY_X
|
||||
0x08, // KEY_C
|
||||
0x09, // KEY_V
|
||||
0x0B, // KEY_B
|
||||
0x2D, // KEY_N
|
||||
0x2E, // KEY_M
|
||||
0x2B, // KEY_COMMA
|
||||
0x2F, // KEY_DOT
|
||||
0x2C, // KEY_SLASH
|
||||
0x38, // KEY_RIGHTSHIFT
|
||||
0x43, // KEY_KPASTERISK
|
||||
0x37, // KEY_LEFTALT
|
||||
0x31, // KEY_SPACE
|
||||
0x39, // KEY_CAPSLOCK
|
||||
0x7A, // KEY_F1
|
||||
0x78, // KEY_F2
|
||||
0x63, // KEY_F3
|
||||
0x76, // KEY_F4
|
||||
0x60, // KEY_F5
|
||||
0x61, // KEY_F6
|
||||
0x62, // KEY_F7
|
||||
0x64, // KEY_F8
|
||||
0x65, // KEY_F9
|
||||
0x6D, // KEY_F10
|
||||
0x47, // KEY_NUMLOCK
|
||||
0x37, // KEY_SCROLLLOCK
|
||||
0x59, // KEY_KP7
|
||||
0x5B, // KEY_KP8
|
||||
0x5C, // KEY_KP9
|
||||
0x4E, // KEY_KPMINUS
|
||||
0x56, // KEY_KP4
|
||||
0x57, // KEY_KP5
|
||||
0x58, // KEY_KP6
|
||||
0x45, // KEY_KPPLUS
|
||||
0x53, // KEY_KP1
|
||||
0x54, // KEY_KP2
|
||||
0x55, // KEY_KP3
|
||||
0x52, // KEY_KP0
|
||||
0x41, // KEY_KPDOT
|
||||
-1,
|
||||
-1, // KEY_ZENKAKUHANKAKU
|
||||
-1, // KEY_102ND
|
||||
0x67, // KEY_F11
|
||||
0x6F, // KEY_F12
|
||||
-1, // KEY_RO
|
||||
-1, // KEY_KATAKANA
|
||||
-1, // KEY_HIRAGANA
|
||||
-1, // KEY_HENKAN
|
||||
-1, // KEY_KATAKANAHIRAGANA
|
||||
-1, // KEY_MUHENKAN
|
||||
-1, // KEY_KPJPCOMMA
|
||||
0x4C, // KEY_KPENTER
|
||||
0x36, // KEY_RIGHTCTRL
|
||||
0x4B, // KEY_KPSLASH
|
||||
0x7F, // KEY_SYSRQ
|
||||
0x37, // KEY_RIGHTALT
|
||||
0x6E, // KEY_LINEFEED
|
||||
0x73, // KEY_HOME
|
||||
0x3E, // KEY_UP
|
||||
0x74, // KEY_PAGEUP
|
||||
0x3B, // KEY_LEFT
|
||||
0x3C, // KEY_RIGHT
|
||||
0x77, // KEY_END
|
||||
0x3D, // KEY_DOWN
|
||||
0x79, // KEY_PAGEDOWN
|
||||
0x72, // KEY_INSERT
|
||||
0x33, // KEY_DELETE
|
||||
-1, // KEY_MACRO
|
||||
-1, // KEY_MUTE
|
||||
-1, // KEY_VOLUMEDOWN
|
||||
-1, // KEY_VOLUMEUP
|
||||
0x7F, // KEY_POWER /* SC System Power Down */
|
||||
0x51, // KEY_KPEQUAL
|
||||
0x4E, // KEY_KPPLUSMINUS
|
||||
-1, // KEY_PAUSE
|
||||
-1, // KEY_SCALE /* AL Compiz Scale (Expose) */
|
||||
0x2B, // KEY_KPCOMMA
|
||||
-1, // KEY_HANGEUL
|
||||
-1, // KEY_HANJA
|
||||
-1, // KEY_YEN
|
||||
0x3A, // KEY_LEFTMETA
|
||||
0x3A, // KEY_RIGHTMETA
|
||||
-1 // KEY_COMPOSE
|
||||
-1, // KEY_RESERVED
|
||||
0x35, // KEY_ESC
|
||||
0x12, // KEY_1
|
||||
0x13, // KEY_2
|
||||
0x14, // KEY_3
|
||||
0x15, // KEY_4
|
||||
0x17, // KEY_5
|
||||
0x16, // KEY_6
|
||||
0x1A, // KEY_7
|
||||
0x1C, // KEY_8
|
||||
0x19, // KEY_9
|
||||
0x1D, // KEY_0
|
||||
0x1B, // KEY_MINUS
|
||||
0x18, // KEY_EQUAL
|
||||
0x3B, // KEY_BACKSPACE0
|
||||
0x30, // KEY_TAB
|
||||
0x0C, // KEY_Q
|
||||
0x0D, // KEY_W
|
||||
0x0E, // KEY_E
|
||||
0x0F, // KEY_R
|
||||
0x11, // KEY_T
|
||||
0x10, // KEY_Y
|
||||
0x20, // KEY_U
|
||||
0x22, // KEY_I
|
||||
0x1F, // KEY_O
|
||||
0x23, // KEY_P
|
||||
0x21, // KEY_LEFTBRACE
|
||||
0x1E, // KEY_RIGHTBRACE
|
||||
0x24, // KEY_ENTER
|
||||
0x36, // KEY_LEFTCTRL
|
||||
0x00, // KEY_A
|
||||
0x01, // KEY_S
|
||||
0x02, // KEY_D
|
||||
0x03, // KEY_F
|
||||
0x05, // KEY_G
|
||||
0x04, // KEY_H
|
||||
0x26, // KEY_J
|
||||
0x28, // KEY_K
|
||||
0x25, // KEY_L
|
||||
0x29, // KEY_SEMICOLON
|
||||
0x27, // KEY_APOSTROPHE
|
||||
0x32, // KEY_GRAVE
|
||||
0x38, // KEY_LEFTSHIFT
|
||||
0x2A, // KEY_BACKSLASH
|
||||
0x06, // KEY_Z
|
||||
0x07, // KEY_X
|
||||
0x08, // KEY_C
|
||||
0x09, // KEY_V
|
||||
0x0B, // KEY_B
|
||||
0x2D, // KEY_N
|
||||
0x2E, // KEY_M
|
||||
0x2B, // KEY_COMMA
|
||||
0x2F, // KEY_DOT
|
||||
0x2C, // KEY_SLASH
|
||||
0x38, // KEY_RIGHTSHIFT
|
||||
0x43, // KEY_KPASTERISK
|
||||
0x37, // KEY_LEFTALT
|
||||
0x31, // KEY_SPACE
|
||||
0x39, // KEY_CAPSLOCK
|
||||
0x7A, // KEY_F1
|
||||
0x78, // KEY_F2
|
||||
0x63, // KEY_F3
|
||||
0x76, // KEY_F4
|
||||
0x60, // KEY_F5
|
||||
0x61, // KEY_F6
|
||||
0x62, // KEY_F7
|
||||
0x64, // KEY_F8
|
||||
0x65, // KEY_F9
|
||||
0x6D, // KEY_F10
|
||||
0x47, // KEY_NUMLOCK
|
||||
0x37, // KEY_SCROLLLOCK
|
||||
0x59, // KEY_KP7
|
||||
0x5B, // KEY_KP8
|
||||
0x5C, // KEY_KP9
|
||||
0x4E, // KEY_KPMINUS
|
||||
0x56, // KEY_KP4
|
||||
0x57, // KEY_KP5
|
||||
0x58, // KEY_KP6
|
||||
0x45, // KEY_KPPLUS
|
||||
0x53, // KEY_KP1
|
||||
0x54, // KEY_KP2
|
||||
0x55, // KEY_KP3
|
||||
0x52, // KEY_KP0
|
||||
0x41, // KEY_KPDOT
|
||||
-1,
|
||||
-1, // KEY_ZENKAKUHANKAKU
|
||||
-1, // KEY_102ND
|
||||
0x67, // KEY_F11
|
||||
0x6F, // KEY_F12
|
||||
-1, // KEY_RO
|
||||
-1, // KEY_KATAKANA
|
||||
-1, // KEY_HIRAGANA
|
||||
-1, // KEY_HENKAN
|
||||
-1, // KEY_KATAKANAHIRAGANA
|
||||
-1, // KEY_MUHENKAN
|
||||
-1, // KEY_KPJPCOMMA
|
||||
0x4C, // KEY_KPENTER
|
||||
0x36, // KEY_RIGHTCTRL
|
||||
0x4B, // KEY_KPSLASH
|
||||
0x7F, // KEY_SYSRQ
|
||||
0x37, // KEY_RIGHTALT
|
||||
0x6E, // KEY_LINEFEED
|
||||
0x73, // KEY_HOME
|
||||
0x3E, // KEY_UP
|
||||
0x74, // KEY_PAGEUP
|
||||
0x3B, // KEY_LEFT
|
||||
0x3C, // KEY_RIGHT
|
||||
0x77, // KEY_END
|
||||
0x3D, // KEY_DOWN
|
||||
0x79, // KEY_PAGEDOWN
|
||||
0x72, // KEY_INSERT
|
||||
0x33, // KEY_DELETE
|
||||
-1, // KEY_MACRO
|
||||
-1, // KEY_MUTE
|
||||
-1, // KEY_VOLUMEDOWN
|
||||
-1, // KEY_VOLUMEUP
|
||||
0x7F, // KEY_POWER /* SC System Power Down */
|
||||
0x51, // KEY_KPEQUAL
|
||||
0x4E, // KEY_KPPLUSMINUS
|
||||
-1, // KEY_PAUSE
|
||||
-1, // KEY_SCALE /* AL Compiz Scale (Expose) */
|
||||
0x2B, // KEY_KPCOMMA
|
||||
-1, // KEY_HANGEUL
|
||||
-1, // KEY_HANJA
|
||||
-1, // KEY_YEN
|
||||
0x3A, // KEY_LEFTMETA
|
||||
0x3A, // KEY_RIGHTMETA
|
||||
-1 // KEY_COMPOSE
|
||||
};
|
||||
struct termios org_tio;
|
||||
struct fb_var_screeninfo orig_vinfo;
|
||||
struct fb_var_screeninfo vinfo;
|
||||
struct fb_fix_screeninfo finfo;
|
||||
int pix_size, g_screen_mdepth, g_use_shmem = 1;
|
||||
#define MOUSE_LBTN_DOWN 0x01
|
||||
#define MOUSE_MBTN_DOWN 0x02
|
||||
#define MOUSE_RBTN_DOWN 0x04
|
||||
#define MOUSE_LBTN_UP 0x00
|
||||
#define MOUSE_MBTN_UP 0x00
|
||||
#define MOUSE_RBTN_UP 0x00
|
||||
#define MOUSE_BTN_ACTIVE 0x07
|
||||
#define UPDATE_INPUT_MOUSE 0x10
|
||||
int pix_size, g_screen_mdepth, g_use_shmem = 1;
|
||||
#define MOUSE_LBTN_DOWN 0x01
|
||||
#define MOUSE_MBTN_DOWN 0x02
|
||||
#define MOUSE_RBTN_DOWN 0x04
|
||||
#define MOUSE_LBTN_UP 0x00
|
||||
#define MOUSE_MBTN_UP 0x00
|
||||
#define MOUSE_RBTN_UP 0x00
|
||||
#define MOUSE_BTN_ACTIVE 0x07
|
||||
#define UPDATE_INPUT_MOUSE 0x10
|
||||
#define MAX_EVDEV 8
|
||||
char *fb_ptr, g_inputstate = 0;
|
||||
int evfd[MAX_EVDEV], evdevs, termfd, fbfd = 0;
|
||||
int evfd[MAX_EVDEV], evdevs, termfd, fbfd = 0;
|
||||
/*
|
||||
* Clean up
|
||||
*/
|
||||
void xdriver_end(void)
|
||||
{
|
||||
char c;
|
||||
static char xexit = 0;
|
||||
if (!xexit)
|
||||
void xdriver_end(void) {
|
||||
char c;
|
||||
static char xexit = 0;
|
||||
if (!xexit)
|
||||
{
|
||||
// cleanup
|
||||
munmap(fb_ptr, finfo.smem_len);
|
||||
ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo);
|
||||
close(fbfd);
|
||||
if (termfd > 0)
|
||||
{
|
||||
// cleanup
|
||||
munmap(fb_ptr, finfo.smem_len);
|
||||
ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo);
|
||||
close(fbfd);
|
||||
if (termfd > 0)
|
||||
{
|
||||
// Flush input
|
||||
while (read(termfd, &c, 1) == 1);
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
tcsetattr(termfd, TCSANOW, &org_tio);
|
||||
close(termfd);
|
||||
}
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
while (evdevs--)
|
||||
close(evfd[evdevs]);
|
||||
xexit = 1;
|
||||
// Flush input
|
||||
while (read(termfd, &c, 1) == 1);
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
tcsetattr(termfd, TCSANOW, &org_tio);
|
||||
close(termfd);
|
||||
}
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
while (evdevs--)
|
||||
close(evfd[evdevs]);
|
||||
xexit = 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Init framebuffer and input
|
||||
*/
|
||||
void dev_video_init(void)
|
||||
{
|
||||
int i;
|
||||
char evdevname[20];
|
||||
struct termios termio;
|
||||
void dev_video_init(void) {
|
||||
int i;
|
||||
char evdevname[20];
|
||||
struct termios termio;
|
||||
|
||||
// Set graphics mode on console
|
||||
if ((termfd = open("/dev/tty", O_RDWR)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error opening tty device.\n");
|
||||
exit(-1);
|
||||
}
|
||||
// Save input settings.
|
||||
tcgetattr(termfd, &termio); /* save current port settings */
|
||||
memcpy(&org_tio, &termio, sizeof(struct termios));
|
||||
ioctl(termfd, KDSETMODE, KD_GRAPHICS);
|
||||
// Open the file for reading and writing
|
||||
if ((fbfd = open("/dev/fb0", O_RDWR)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error opening framebuffer device.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// Get variable screen information
|
||||
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
|
||||
{
|
||||
fprintf(stderr, "Error reading variable screen information.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// Store for reset(copy vinfo to vinfo_orig)
|
||||
memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo));
|
||||
// Change variable info
|
||||
//vinfo.bits_per_pixel = 8;
|
||||
// Change resolution
|
||||
vinfo.xres = 640;
|
||||
vinfo.yres = 400;
|
||||
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
|
||||
{
|
||||
fprintf(stderr, "Error setting variable screen information (640x400x8).\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// Get fixed screen information
|
||||
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
|
||||
{
|
||||
fprintf(stderr, "Error reading fixed screen information.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// map fb to user mem
|
||||
fb_ptr = (char*)mmap(0,
|
||||
finfo.smem_len,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fbfd,
|
||||
0);
|
||||
if ((int)fb_ptr == -1)
|
||||
{
|
||||
printf("Failed to mmap framebuffer.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit (-1);
|
||||
}
|
||||
g_screen_depth = vinfo.bits_per_pixel;
|
||||
g_screen_mdepth = g_screen_depth;
|
||||
if (g_screen_depth > 8)
|
||||
g_screen_mdepth = 16;
|
||||
if (g_screen_depth > 16)
|
||||
g_screen_mdepth = 32;
|
||||
pix_size = g_screen_mdepth / 8;
|
||||
if (vinfo.bits_per_pixel > 8)
|
||||
{
|
||||
g_red_mask = (1 << vinfo.red.length) - 1;
|
||||
g_green_mask = (1 << vinfo.green.length) - 1;
|
||||
g_blue_mask = (1 << vinfo.blue.length) - 1;
|
||||
g_red_left_shift = vinfo.red.offset;
|
||||
g_green_left_shift = vinfo.green.offset;
|
||||
g_blue_left_shift = vinfo.blue.offset;
|
||||
g_red_right_shift = 8 - vinfo.red.length;
|
||||
g_green_right_shift = 8 - vinfo.green.length;
|
||||
g_blue_right_shift = 8 - vinfo.blue.length;
|
||||
}
|
||||
video_get_kimages();
|
||||
if (g_screen_depth > 8)
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, g_screen_mdepth);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
video_update_color_raw(i, g_lores_colors[i & 0xf]);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
fclose(stdin);
|
||||
freopen("gsport.log", "w+", stdout);
|
||||
freopen("gsport.err", "w+", stderr);
|
||||
termio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD;
|
||||
termio.c_iflag = IGNPAR;
|
||||
termio.c_oflag = 0;
|
||||
termio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||
termio.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||
termio.c_cc[VMIN] = 0; /* non-blocking read */
|
||||
tcsetattr(termfd, TCSANOW, &termio);
|
||||
// Open input event devices
|
||||
for (evdevs = 0; evdevs < MAX_EVDEV; evdevs++)
|
||||
{
|
||||
sprintf(evdevname, "/dev/input/event%c", evdevs + '0');
|
||||
if ((evfd[evdevs] = open(evdevname, O_RDONLY|O_NONBLOCK)) < 0)
|
||||
break;
|
||||
}
|
||||
g_video_act_margin_left = 0;
|
||||
g_video_act_margin_right = 1;
|
||||
g_video_act_margin_top = 0;
|
||||
g_video_act_margin_bottom = 0;
|
||||
// Set graphics mode on console
|
||||
if ((termfd = open("/dev/tty", O_RDWR)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error opening tty device.\n");
|
||||
exit(-1);
|
||||
}
|
||||
// Save input settings.
|
||||
tcgetattr(termfd, &termio); /* save current port settings */
|
||||
memcpy(&org_tio, &termio, sizeof(struct termios));
|
||||
ioctl(termfd, KDSETMODE, KD_GRAPHICS);
|
||||
// Open the file for reading and writing
|
||||
if ((fbfd = open("/dev/fb0", O_RDWR)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error opening framebuffer device.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// Get variable screen information
|
||||
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
|
||||
{
|
||||
fprintf(stderr, "Error reading variable screen information.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// Store for reset(copy vinfo to vinfo_orig)
|
||||
memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo));
|
||||
// Change variable info
|
||||
//vinfo.bits_per_pixel = 8;
|
||||
// Change resolution
|
||||
vinfo.xres = 640;
|
||||
vinfo.yres = 400;
|
||||
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
|
||||
{
|
||||
fprintf(stderr, "Error setting variable screen information (640x400x8).\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// Get fixed screen information
|
||||
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
|
||||
{
|
||||
fprintf(stderr, "Error reading fixed screen information.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit(-1);
|
||||
}
|
||||
// map fb to user mem
|
||||
fb_ptr = (char*)mmap(0,
|
||||
finfo.smem_len,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fbfd,
|
||||
0);
|
||||
if ((int)fb_ptr == -1)
|
||||
{
|
||||
printf("Failed to mmap framebuffer.\n");
|
||||
ioctl(termfd, KDSETMODE, KD_TEXT);
|
||||
exit (-1);
|
||||
}
|
||||
g_screen_depth = vinfo.bits_per_pixel;
|
||||
g_screen_mdepth = g_screen_depth;
|
||||
if (g_screen_depth > 8)
|
||||
g_screen_mdepth = 16;
|
||||
if (g_screen_depth > 16)
|
||||
g_screen_mdepth = 32;
|
||||
pix_size = g_screen_mdepth / 8;
|
||||
if (vinfo.bits_per_pixel > 8)
|
||||
{
|
||||
g_red_mask = (1 << vinfo.red.length) - 1;
|
||||
g_green_mask = (1 << vinfo.green.length) - 1;
|
||||
g_blue_mask = (1 << vinfo.blue.length) - 1;
|
||||
g_red_left_shift = vinfo.red.offset;
|
||||
g_green_left_shift = vinfo.green.offset;
|
||||
g_blue_left_shift = vinfo.blue.offset;
|
||||
g_red_right_shift = 8 - vinfo.red.length;
|
||||
g_green_right_shift = 8 - vinfo.green.length;
|
||||
g_blue_right_shift = 8 - vinfo.blue.length;
|
||||
}
|
||||
video_get_kimages();
|
||||
if (g_screen_depth > 8)
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, g_screen_mdepth);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
video_update_color_raw(i, g_lores_colors[i & 0xf]);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
fclose(stdin);
|
||||
freopen("gsport.log", "w+", stdout);
|
||||
freopen("gsport.err", "w+", stderr);
|
||||
termio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD;
|
||||
termio.c_iflag = IGNPAR;
|
||||
termio.c_oflag = 0;
|
||||
termio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||
termio.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||
termio.c_cc[VMIN] = 0; /* non-blocking read */
|
||||
tcsetattr(termfd, TCSANOW, &termio);
|
||||
// Open input event devices
|
||||
for (evdevs = 0; evdevs < MAX_EVDEV; evdevs++)
|
||||
{
|
||||
sprintf(evdevname, "/dev/input/event%c", evdevs + '0');
|
||||
if ((evfd[evdevs] = open(evdevname, O_RDONLY|O_NONBLOCK)) < 0)
|
||||
break;
|
||||
}
|
||||
g_video_act_margin_left = 0;
|
||||
g_video_act_margin_right = 1;
|
||||
g_video_act_margin_top = 0;
|
||||
g_video_act_margin_bottom = 0;
|
||||
}
|
||||
/*
|
||||
* Colormap
|
||||
*/
|
||||
__u16 cmapred[256], cmapgreen[256], cmapblue[256];
|
||||
int cmapstart, cmaplen, cmapdirty = 0;
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb)
|
||||
{
|
||||
cmapred[col_num] = red | (red << 8);
|
||||
cmapgreen[col_num] = green | (green << 8);
|
||||
cmapblue[col_num] = blue | (blue << 8);
|
||||
if (cmapdirty == 0)
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb) {
|
||||
cmapred[col_num] = red | (red << 8);
|
||||
cmapgreen[col_num] = green | (green << 8);
|
||||
cmapblue[col_num] = blue | (blue << 8);
|
||||
if (cmapdirty == 0)
|
||||
{
|
||||
cmapstart = col_num;
|
||||
cmaplen = 1;
|
||||
cmapdirty = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (col_num < cmapstart)
|
||||
{
|
||||
cmapstart = col_num;
|
||||
cmaplen = 1;
|
||||
cmapdirty = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (col_num < cmapstart)
|
||||
{
|
||||
cmaplen += cmapstart - col_num;
|
||||
cmapstart = col_num;
|
||||
}
|
||||
else if (col_num > cmapstart + cmaplen)
|
||||
cmaplen = col_num - cmapstart + 1;
|
||||
cmaplen += cmapstart - col_num;
|
||||
cmapstart = col_num;
|
||||
}
|
||||
else if (col_num > cmapstart + cmaplen)
|
||||
cmaplen = col_num - cmapstart + 1;
|
||||
}
|
||||
}
|
||||
void x_update_physical_colormap(void)
|
||||
{
|
||||
struct fb_cmap fbcol;
|
||||
if (cmapdirty)
|
||||
{
|
||||
cmapdirty = 0;
|
||||
fbcol.start = cmapstart;
|
||||
fbcol.len = cmaplen;
|
||||
fbcol.red = cmapred;
|
||||
fbcol.green = cmapgreen;
|
||||
fbcol.blue = cmapblue;
|
||||
fbcol.transp = NULL;
|
||||
ioctl(fbfd, FBIOPUTCMAP, &fbcol);
|
||||
}
|
||||
void x_update_physical_colormap(void) {
|
||||
struct fb_cmap fbcol;
|
||||
if (cmapdirty)
|
||||
{
|
||||
cmapdirty = 0;
|
||||
fbcol.start = cmapstart;
|
||||
fbcol.len = cmaplen;
|
||||
fbcol.red = cmapred;
|
||||
fbcol.green = cmapgreen;
|
||||
fbcol.blue = cmapblue;
|
||||
fbcol.transp = NULL;
|
||||
ioctl(fbfd, FBIOPUTCMAP, &fbcol);
|
||||
}
|
||||
}
|
||||
void show_xcolor_array(void)
|
||||
{
|
||||
void show_xcolor_array(void) {
|
||||
}
|
||||
/*
|
||||
* Screen update
|
||||
*/
|
||||
void x_get_kimage(Kimage *kimage_ptr)
|
||||
{
|
||||
kimage_ptr->data_ptr = (byte *)malloc(kimage_ptr->width_req * kimage_ptr->height * kimage_ptr->mdepth / 8);
|
||||
void x_get_kimage(Kimage *kimage_ptr) {
|
||||
kimage_ptr->data_ptr = (byte *)malloc(kimage_ptr->width_req * kimage_ptr->height * kimage_ptr->mdepth / 8);
|
||||
}
|
||||
void x_release_kimage(Kimage* kimage_ptr)
|
||||
{
|
||||
if (kimage_ptr->data_ptr)
|
||||
if (kimage_ptr->width_req != 640 || kimage_ptr->height != 400)
|
||||
free(kimage_ptr->data_ptr);
|
||||
kimage_ptr->data_ptr = NULL;
|
||||
void x_release_kimage(Kimage* kimage_ptr) {
|
||||
if (kimage_ptr->data_ptr)
|
||||
if (kimage_ptr->width_req != 640 || kimage_ptr->height != 400)
|
||||
free(kimage_ptr->data_ptr);
|
||||
kimage_ptr->data_ptr = NULL;
|
||||
}
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height)
|
||||
{
|
||||
byte *src_ptr, *dst_ptr;
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height) {
|
||||
byte *src_ptr, *dst_ptr;
|
||||
|
||||
// Copy sub-image to framebuffer
|
||||
dst_ptr = (byte *)fb_ptr + desty * finfo.line_length + destx * pix_size;
|
||||
src_ptr = kimage_ptr->data_ptr + (srcy * kimage_ptr->width_act + srcx) * pix_size;
|
||||
width *= pix_size;
|
||||
while (height--)
|
||||
{
|
||||
memcpy(dst_ptr, src_ptr, width);
|
||||
dst_ptr += finfo.line_length;
|
||||
src_ptr += kimage_ptr->width_act * pix_size;
|
||||
}
|
||||
// Copy sub-image to framebuffer
|
||||
dst_ptr = (byte *)fb_ptr + desty * finfo.line_length + destx * pix_size;
|
||||
src_ptr = kimage_ptr->data_ptr + (srcy * kimage_ptr->width_act + srcx) * pix_size;
|
||||
width *= pix_size;
|
||||
while (height--)
|
||||
{
|
||||
memcpy(dst_ptr, src_ptr, width);
|
||||
dst_ptr += finfo.line_length;
|
||||
src_ptr += kimage_ptr->width_act * pix_size;
|
||||
}
|
||||
}
|
||||
void x_push_done(void)
|
||||
{
|
||||
void x_push_done(void) {
|
||||
}
|
||||
/*
|
||||
* NOP routines
|
||||
*/
|
||||
void x_dialog_create_gsport_conf(const char *str)
|
||||
{
|
||||
// Just write the config file already...
|
||||
config_write_config_gsplus_file();
|
||||
void x_dialog_create_gsport_conf(const char *str) {
|
||||
// Just write the config file already...
|
||||
config_write_config_gsplus_file();
|
||||
}
|
||||
int x_show_alert(int is_fatal, const char *str)
|
||||
{
|
||||
// Not implemented yet
|
||||
adb_all_keys_up();
|
||||
clear_fatal_logs();
|
||||
return 0;
|
||||
int x_show_alert(int is_fatal, const char *str) {
|
||||
// Not implemented yet
|
||||
adb_all_keys_up();
|
||||
clear_fatal_logs();
|
||||
return 0;
|
||||
}
|
||||
void x_toggle_status_lines(void)
|
||||
{
|
||||
void x_toggle_status_lines(void) {
|
||||
}
|
||||
void x_redraw_status_lines(void)
|
||||
{
|
||||
void x_redraw_status_lines(void) {
|
||||
}
|
||||
void x_hide_pointer(int do_hide)
|
||||
{
|
||||
void x_hide_pointer(int do_hide) {
|
||||
}
|
||||
void x_auto_repeat_on(int must)
|
||||
{
|
||||
void x_auto_repeat_on(int must) {
|
||||
}
|
||||
void x_full_screen(int do_full)
|
||||
{
|
||||
void x_full_screen(int do_full) {
|
||||
}
|
||||
int x_calc_ratio(float x, float y)
|
||||
{
|
||||
return 1;
|
||||
int x_calc_ratio(float x, float y) {
|
||||
return 1;
|
||||
}
|
||||
void clipboard_paste(void)
|
||||
{
|
||||
void clipboard_paste(void) {
|
||||
}
|
||||
int clipboard_get_char(void)
|
||||
{
|
||||
return 0;
|
||||
int clipboard_get_char(void) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Input handling
|
||||
*/
|
||||
void check_input_events(void)
|
||||
{
|
||||
struct input_event ev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < evdevs; i++)
|
||||
// Check input events
|
||||
while (read(evfd[i], &ev, sizeof(struct input_event)) == sizeof(struct input_event))
|
||||
{
|
||||
if (ev.type == EV_REL)
|
||||
{
|
||||
if (ev.code == REL_X)
|
||||
{
|
||||
g_mouse_raw_x += ev.value;
|
||||
if (g_mouse_raw_x < 0)
|
||||
g_mouse_raw_x = 0;
|
||||
if (g_mouse_raw_x > 639)
|
||||
g_mouse_raw_x = 639;
|
||||
}
|
||||
else // REL_Y
|
||||
{
|
||||
g_mouse_raw_y += ev.value;
|
||||
if (g_mouse_raw_y < 0)
|
||||
g_mouse_raw_y = 0;
|
||||
if (g_mouse_raw_y > 399)
|
||||
g_mouse_raw_y = 399;
|
||||
}
|
||||
g_inputstate |= UPDATE_INPUT_MOUSE;
|
||||
}
|
||||
else if (ev.type == EV_KEY)
|
||||
{
|
||||
if (ev.code < 128)
|
||||
{
|
||||
void check_input_events(void) {
|
||||
struct input_event ev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < evdevs; i++)
|
||||
// Check input events
|
||||
while (read(evfd[i], &ev, sizeof(struct input_event)) == sizeof(struct input_event))
|
||||
{
|
||||
if (ev.type == EV_REL)
|
||||
{
|
||||
if (ev.code == REL_X)
|
||||
{
|
||||
g_mouse_raw_x += ev.value;
|
||||
if (g_mouse_raw_x < 0)
|
||||
g_mouse_raw_x = 0;
|
||||
if (g_mouse_raw_x > 639)
|
||||
g_mouse_raw_x = 639;
|
||||
}
|
||||
else // REL_Y
|
||||
{
|
||||
g_mouse_raw_y += ev.value;
|
||||
if (g_mouse_raw_y < 0)
|
||||
g_mouse_raw_y = 0;
|
||||
if (g_mouse_raw_y > 399)
|
||||
g_mouse_raw_y = 399;
|
||||
}
|
||||
g_inputstate |= UPDATE_INPUT_MOUSE;
|
||||
}
|
||||
else if (ev.type == EV_KEY)
|
||||
{
|
||||
if (ev.code < 128)
|
||||
{
|
||||
#if 0
|
||||
if ((ev.code == KEY_F10) && SHIFT_DOWN)
|
||||
{
|
||||
//quitEmulator();
|
||||
iwm_shut();
|
||||
xdriver_end();
|
||||
my_exit(1);
|
||||
}
|
||||
if ((ev.code == KEY_F10) && SHIFT_DOWN)
|
||||
{
|
||||
//quitEmulator();
|
||||
iwm_shut();
|
||||
xdriver_end();
|
||||
my_exit(1);
|
||||
}
|
||||
#endif
|
||||
if (keycode_to_a2code[ev.code] >= 0)
|
||||
adb_physical_key_update(keycode_to_a2code[ev.code], !ev.value);
|
||||
}
|
||||
else if (ev.code == BTN_LEFT)
|
||||
{
|
||||
g_inputstate = ev.value ? UPDATE_INPUT_MOUSE | MOUSE_LBTN_DOWN
|
||||
: UPDATE_INPUT_MOUSE | MOUSE_LBTN_UP;
|
||||
}
|
||||
}
|
||||
else if (ev.type == EV_SYN)
|
||||
{
|
||||
if (g_inputstate & UPDATE_INPUT_MOUSE)
|
||||
update_mouse(g_mouse_raw_x, g_mouse_raw_y, g_inputstate & MOUSE_BTN_ACTIVE, MOUSE_BTN_ACTIVE);
|
||||
g_inputstate &= ~UPDATE_INPUT_MOUSE;
|
||||
}
|
||||
}
|
||||
if (keycode_to_a2code[ev.code] >= 0)
|
||||
adb_physical_key_update(keycode_to_a2code[ev.code], !ev.value);
|
||||
}
|
||||
else if (ev.code == BTN_LEFT)
|
||||
{
|
||||
g_inputstate = ev.value ? UPDATE_INPUT_MOUSE | MOUSE_LBTN_DOWN
|
||||
: UPDATE_INPUT_MOUSE | MOUSE_LBTN_UP;
|
||||
}
|
||||
}
|
||||
else if (ev.type == EV_SYN)
|
||||
{
|
||||
if (g_inputstate & UPDATE_INPUT_MOUSE)
|
||||
update_mouse(g_mouse_raw_x, g_mouse_raw_y, g_inputstate & MOUSE_BTN_ACTIVE, MOUSE_BTN_ACTIVE);
|
||||
g_inputstate &= ~UPDATE_INPUT_MOUSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void sig_bye(int signo)
|
||||
{
|
||||
xdriver_end();
|
||||
exit (-1);
|
||||
static void sig_bye(int signo) {
|
||||
xdriver_end();
|
||||
exit (-1);
|
||||
}
|
||||
/*
|
||||
* Application entrypoint
|
||||
*/
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
if (signal(SIGINT, sig_bye) == SIG_ERR)
|
||||
exit(-1);
|
||||
if (signal(SIGHUP, sig_bye) == SIG_ERR)
|
||||
exit(-1);
|
||||
gsplusmain(argc, argv);
|
||||
xdriver_end();
|
||||
return 0;
|
||||
int main(int argc,char *argv[]) {
|
||||
if (signal(SIGINT, sig_bye) == SIG_ERR)
|
||||
exit(-1);
|
||||
if (signal(SIGHUP, sig_bye) == SIG_ERR)
|
||||
exit(-1);
|
||||
gsplusmain(argc, argv);
|
||||
xdriver_end();
|
||||
return 0;
|
||||
}
|
||||
|
|
48
src/glog.c
48
src/glog.c
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -5,37 +11,37 @@
|
|||
#include "glog.h"
|
||||
|
||||
int glog(const char *s) {
|
||||
time_t timer;
|
||||
char buffer[26];
|
||||
struct tm* tm_info;
|
||||
time_t timer;
|
||||
char buffer[26];
|
||||
struct tm* tm_info;
|
||||
|
||||
time(&timer);
|
||||
tm_info = localtime(&timer);
|
||||
time(&timer);
|
||||
tm_info = localtime(&timer);
|
||||
|
||||
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
printf("%s - %s\n", buffer, s);
|
||||
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
printf("%s - %s\n", buffer, s);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int glogf(const char *fmt, ...) {
|
||||
|
||||
time_t timer;
|
||||
char buffer[26];
|
||||
struct tm* tm_info;
|
||||
time_t timer;
|
||||
char buffer[26];
|
||||
struct tm* tm_info;
|
||||
|
||||
time(&timer);
|
||||
tm_info = localtime(&timer);
|
||||
time(&timer);
|
||||
tm_info = localtime(&timer);
|
||||
|
||||
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
|
||||
printf("%s - ", buffer);
|
||||
printf("%s - ", buffer);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
|
||||
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
|
||||
option) any later version.
|
||||
|
||||
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
|
||||
for more details.
|
||||
|
||||
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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include "glog.h"
|
||||
|
@ -42,7 +30,7 @@ int clipboard_get_char() { return 0; }
|
|||
|
||||
void clipboard_paste(void) { }
|
||||
|
||||
void dev_video_init() {
|
||||
void dev_video_init() {
|
||||
|
||||
g_screen_depth = 24;
|
||||
g_screen_mdepth = 32;
|
||||
|
@ -100,4 +88,3 @@ void
|
|||
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
3850
src/host_fst.c
3850
src/host_fst.c
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Copyright (C) 2010 - 2011 by GSport contributors
|
||||
|
||||
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
|
||||
|
||||
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
|
||||
option) any later version.
|
||||
|
||||
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
|
||||
for more details.
|
||||
|
||||
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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include "glog.h"
|
||||
|
@ -28,41 +28,39 @@ SDL_Joystick *gGameController = NULL;
|
|||
|
||||
|
||||
|
||||
extern int g_joystick_native_type1; /* in paddles.c */
|
||||
extern int g_joystick_native_type2; /* in paddles.c */
|
||||
extern int g_joystick_native_type; /* in paddles.c */
|
||||
extern int g_joystick_native_type1; /* in paddles.c */
|
||||
extern int g_joystick_native_type2; /* in paddles.c */
|
||||
extern int g_joystick_native_type; /* in paddles.c */
|
||||
extern int g_joystick_type;
|
||||
extern int g_paddle_buttons;
|
||||
extern int g_paddle_val[];
|
||||
|
||||
|
||||
const char *g_joystick_dev = "/dev/input/js0"; /* default joystick dev file */
|
||||
#define MAX_JOY_NAME 128
|
||||
const char *g_joystick_dev = "/dev/input/js0"; /* default joystick dev file */
|
||||
#define MAX_JOY_NAME 128
|
||||
|
||||
int g_joystick_native_fd = -1;
|
||||
int g_joystick_num_axes = 0;
|
||||
int g_joystick_num_buttons = 0;
|
||||
int g_joystick_number = 0; // SDL2
|
||||
int g_joystick_x_axis = 0; // SDL2
|
||||
int g_joystick_y_axis = 1; // SDL2
|
||||
int g_joystick_button_0 = 0; // SDL2
|
||||
int g_joystick_button_1 = 1; // SDL2
|
||||
int g_joystick_native_fd = -1;
|
||||
int g_joystick_num_axes = 0;
|
||||
int g_joystick_num_buttons = 0;
|
||||
int g_joystick_number = 0; // SDL2
|
||||
int g_joystick_x_axis = 0; // SDL2
|
||||
int g_joystick_y_axis = 1; // SDL2
|
||||
int g_joystick_button_0 = 0; // SDL2
|
||||
int g_joystick_button_1 = 1; // SDL2
|
||||
|
||||
int g_joystick_x2_axis = 2; // SDL2
|
||||
int g_joystick_y2_axis = 3; // SDL2
|
||||
int g_joystick_button_2 = 2; // SDL2
|
||||
int g_joystick_button_3 = 3; // SDL2
|
||||
int g_joystick_x2_axis = 2; // SDL2
|
||||
int g_joystick_y2_axis = 3; // SDL2
|
||||
int g_joystick_button_2 = 2; // SDL2
|
||||
int g_joystick_button_3 = 3; // SDL2
|
||||
#define JOY2SUPPORT
|
||||
|
||||
|
||||
#if defined(HAVE_SDL) && !defined(JOYSTICK_DEFINED)
|
||||
# define JOYSTICK_DEFINED
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
void joystick_init() {
|
||||
int i;
|
||||
if( SDL_Init( SDL_INIT_JOYSTICK ) < 0 ) {
|
||||
glogf( "SDL could not initialize joystick! SDL Error: %s", SDL_GetError() );
|
||||
glogf( "SDL could not initialize joystick! SDL Error: %s", SDL_GetError() );
|
||||
} else {
|
||||
glog("SDL2 joystick initialized");
|
||||
}
|
||||
|
@ -70,16 +68,16 @@ joystick_init()
|
|||
glog("No joysticks detected");
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
} else {
|
||||
// @todo: make controller configurable
|
||||
// @todo: add multiple controller support
|
||||
gGameController = SDL_JoystickOpen( g_joystick_number );
|
||||
if( gGameController == NULL ) {
|
||||
glogf( "Warning: Unable to open game controller! SDL Error: %s", SDL_GetError() );
|
||||
}
|
||||
}
|
||||
// @todo: make controller configurable
|
||||
// @todo: add multiple controller support
|
||||
gGameController = SDL_JoystickOpen( g_joystick_number );
|
||||
if( gGameController == NULL ) {
|
||||
glogf( "Warning: Unable to open game controller! SDL Error: %s", SDL_GetError() );
|
||||
}
|
||||
}
|
||||
g_joystick_native_type = 2;
|
||||
g_joystick_native_type1 = 2;
|
||||
g_joystick_native_type2 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 180;
|
||||
}
|
||||
|
@ -88,43 +86,39 @@ joystick_init()
|
|||
joystick_update(0.0);
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update(double dcycs)
|
||||
{
|
||||
void joystick_update(double dcycs) {
|
||||
if (gGameController) {
|
||||
SDL_JoystickUpdate();
|
||||
g_paddle_val[0] = (int)SDL_JoystickGetAxis(gGameController, g_joystick_x_axis); // default is 0
|
||||
g_paddle_val[1] = (int)SDL_JoystickGetAxis(gGameController, g_joystick_y_axis); // default is 1
|
||||
g_paddle_val[2] = (int)SDL_JoystickGetAxis(gGameController, g_joystick_x2_axis); // default is 2
|
||||
g_paddle_val[3] = (int)SDL_JoystickGetAxis(gGameController, g_joystick_y2_axis); // default is 3
|
||||
|
||||
|
||||
if (SDL_JoystickGetButton(gGameController, g_joystick_button_0)) {
|
||||
g_paddle_buttons = g_paddle_buttons | 1;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~1);
|
||||
}
|
||||
g_paddle_buttons = g_paddle_buttons | 1;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~1);
|
||||
}
|
||||
if (SDL_JoystickGetButton(gGameController, g_joystick_button_1)) {
|
||||
g_paddle_buttons = g_paddle_buttons | 2;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~2);
|
||||
}
|
||||
g_paddle_buttons = g_paddle_buttons | 2;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~2);
|
||||
}
|
||||
if (SDL_JoystickGetButton(gGameController, g_joystick_button_2)) {
|
||||
g_paddle_buttons = g_paddle_buttons | 4;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~4);
|
||||
}
|
||||
g_paddle_buttons = g_paddle_buttons | 4;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~4);
|
||||
}
|
||||
if (SDL_JoystickGetButton(gGameController, g_joystick_button_3)) {
|
||||
g_paddle_buttons = g_paddle_buttons | 8;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~8);
|
||||
}
|
||||
g_paddle_buttons = g_paddle_buttons | 8;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~8);
|
||||
}
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_buttons()
|
||||
{
|
||||
void joystick_update_buttons() {
|
||||
}
|
||||
|
||||
void joystick_shut() {
|
||||
|
@ -139,202 +133,190 @@ void joystick_shut() {
|
|||
|
||||
#if defined(__linux__) && !defined(JOYSTICK_DEFINED)
|
||||
# define JOYSTICK_DEFINED
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
char joy_name[MAX_JOY_NAME];
|
||||
int version;
|
||||
int fd;
|
||||
int i;
|
||||
void joystick_init() {
|
||||
char joy_name[MAX_JOY_NAME];
|
||||
int version;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
fd = open(g_joystick_dev, O_RDONLY | O_NONBLOCK);
|
||||
if(fd < 0) {
|
||||
printf("Unable to open joystick dev file: %s, errno: %d\n",
|
||||
g_joystick_dev, errno);
|
||||
printf("Defaulting to mouse joystick\n");
|
||||
return;
|
||||
}
|
||||
fd = open(g_joystick_dev, O_RDONLY | O_NONBLOCK);
|
||||
if(fd < 0) {
|
||||
printf("Unable to open joystick dev file: %s, errno: %d\n",
|
||||
g_joystick_dev, errno);
|
||||
printf("Defaulting to mouse joystick\n");
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(&joy_name[0], "Unknown Joystick");
|
||||
version = 0x800;
|
||||
strcpy(&joy_name[0], "Unknown Joystick");
|
||||
version = 0x800;
|
||||
|
||||
ioctl(fd, JSIOCGNAME(MAX_JOY_NAME), &joy_name[0]);
|
||||
ioctl(fd, JSIOCGAXES, &g_joystick_num_axes);
|
||||
ioctl(fd, JSIOCGBUTTONS, &g_joystick_num_buttons);
|
||||
ioctl(fd, JSIOCGVERSION, &version);
|
||||
ioctl(fd, JSIOCGNAME(MAX_JOY_NAME), &joy_name[0]);
|
||||
ioctl(fd, JSIOCGAXES, &g_joystick_num_axes);
|
||||
ioctl(fd, JSIOCGBUTTONS, &g_joystick_num_buttons);
|
||||
ioctl(fd, JSIOCGVERSION, &version);
|
||||
|
||||
printf("Detected joystick: %s [%d axes, %d buttons vers: %08x]\n",
|
||||
joy_name, g_joystick_num_axes, g_joystick_num_buttons,
|
||||
version);
|
||||
printf("Detected joystick: %s [%d axes, %d buttons vers: %08x]\n",
|
||||
joy_name, g_joystick_num_axes, g_joystick_num_buttons,
|
||||
version);
|
||||
|
||||
g_joystick_native_type1 = 1;
|
||||
g_joystick_native_type2 = -1;
|
||||
g_joystick_native_fd = fd;
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 32767;
|
||||
}
|
||||
g_paddle_buttons = 0xc;
|
||||
g_joystick_native_type1 = 1;
|
||||
g_joystick_native_type2 = -1;
|
||||
g_joystick_native_fd = fd;
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 32767;
|
||||
}
|
||||
g_paddle_buttons = 0xc;
|
||||
|
||||
joystick_update(0.0);
|
||||
joystick_update(0.0);
|
||||
}
|
||||
|
||||
/* joystick_update_linux() called from paddles.c. Update g_paddle_val[] */
|
||||
/* and g_paddle_buttons with current information */
|
||||
void
|
||||
joystick_update(double dcycs)
|
||||
{
|
||||
struct js_event js; /* the linux joystick event record */
|
||||
int mask;
|
||||
int val;
|
||||
int num;
|
||||
int type;
|
||||
int ret;
|
||||
int len;
|
||||
int i;
|
||||
void joystick_update(double dcycs) {
|
||||
struct js_event js; /* the linux joystick event record */
|
||||
int mask;
|
||||
int val;
|
||||
int num;
|
||||
int type;
|
||||
int ret;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
/* suck up to 20 events, then give up */
|
||||
len = sizeof(struct js_event);
|
||||
for(i = 0; i < 20; i++) {
|
||||
ret = read(g_joystick_native_fd, &js, len);
|
||||
if(ret != len) {
|
||||
/* just get out */
|
||||
break;
|
||||
}
|
||||
type = js.type & ~JS_EVENT_INIT;
|
||||
val = js.value;
|
||||
num = js.number & 3; /* clamp to 0-3 */
|
||||
switch(type) {
|
||||
case JS_EVENT_BUTTON:
|
||||
mask = 1 << num;
|
||||
if(val) {
|
||||
val = mask;
|
||||
}
|
||||
g_paddle_buttons = (g_paddle_buttons & ~mask) | val;
|
||||
break;
|
||||
case JS_EVENT_AXIS:
|
||||
/* val is -32767 to +32767 */
|
||||
g_paddle_val[num] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* suck up to 20 events, then give up */
|
||||
len = sizeof(struct js_event);
|
||||
for(i = 0; i < 20; i++) {
|
||||
ret = read(g_joystick_native_fd, &js, len);
|
||||
if(ret != len) {
|
||||
/* just get out */
|
||||
break;
|
||||
}
|
||||
type = js.type & ~JS_EVENT_INIT;
|
||||
val = js.value;
|
||||
num = js.number & 3; /* clamp to 0-3 */
|
||||
switch(type) {
|
||||
case JS_EVENT_BUTTON:
|
||||
mask = 1 << num;
|
||||
if(val) {
|
||||
val = mask;
|
||||
}
|
||||
g_paddle_buttons = (g_paddle_buttons & ~mask) | val;
|
||||
break;
|
||||
case JS_EVENT_AXIS:
|
||||
/* val is -32767 to +32767 */
|
||||
g_paddle_val[num] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if(i > 0) {
|
||||
// Note from Dave Schmenk: paddle_update_trigger_dcycles(dcycs) always has to be called to keep the triggers current.
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
// }
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_buttons()
|
||||
{
|
||||
void joystick_update_buttons() {
|
||||
}
|
||||
#endif /* LINUX */
|
||||
|
||||
#if defined(_WIN32) && !defined(JOYSTICK_DEFINED)
|
||||
# define JOYSTICK_DEFINED
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
JOYINFO info;
|
||||
JOYCAPS joycap;
|
||||
MMRESULT ret1, ret2;
|
||||
int i;
|
||||
void joystick_init() {
|
||||
JOYINFO info;
|
||||
JOYCAPS joycap;
|
||||
MMRESULT ret1, ret2;
|
||||
int i;
|
||||
|
||||
// Check that there is a joystick device
|
||||
if(joyGetNumDevs() <= 0) {
|
||||
glog("No joystick hardware detected");
|
||||
g_joystick_native_type1 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
return;
|
||||
}
|
||||
// Check that there is a joystick device
|
||||
if(joyGetNumDevs() <= 0) {
|
||||
glog("No joystick hardware detected");
|
||||
g_joystick_native_type1 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
g_joystick_native_type1 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
g_joystick_native_type1 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
|
||||
// Check that at least joystick 1 or joystick 2 is available
|
||||
ret1 = joyGetPos(JOYSTICKID1, &info);
|
||||
ret2 = joyGetDevCaps(JOYSTICKID1, &joycap, sizeof(joycap));
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_joystick_native_type1 = JOYSTICKID1;
|
||||
printf("Joystick #1 = %s\n", joycap.szPname);
|
||||
g_joystick_native_type = JOYSTICKID1;
|
||||
}
|
||||
ret1 = joyGetPos(JOYSTICKID2, &info);
|
||||
ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap));
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_joystick_native_type2 = JOYSTICKID2;
|
||||
printf("Joystick #2 = %s\n", joycap.szPname);
|
||||
if(g_joystick_native_type < 0) {
|
||||
g_joystick_native_type = JOYSTICKID2;
|
||||
}
|
||||
}
|
||||
// Check that at least joystick 1 or joystick 2 is available
|
||||
ret1 = joyGetPos(JOYSTICKID1, &info);
|
||||
ret2 = joyGetDevCaps(JOYSTICKID1, &joycap, sizeof(joycap));
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_joystick_native_type1 = JOYSTICKID1;
|
||||
printf("Joystick #1 = %s\n", joycap.szPname);
|
||||
g_joystick_native_type = JOYSTICKID1;
|
||||
}
|
||||
ret1 = joyGetPos(JOYSTICKID2, &info);
|
||||
ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap));
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_joystick_native_type2 = JOYSTICKID2;
|
||||
printf("Joystick #2 = %s\n", joycap.szPname);
|
||||
if(g_joystick_native_type < 0) {
|
||||
g_joystick_native_type = JOYSTICKID2;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_joystick_native_type1<0 && g_joystick_native_type2 <0) {
|
||||
glog("No joystick is attached");
|
||||
return;
|
||||
}
|
||||
if (g_joystick_native_type1<0 && g_joystick_native_type2 <0) {
|
||||
glog("No joystick is attached");
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 32767;
|
||||
}
|
||||
g_paddle_buttons = 0xc;
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 32767;
|
||||
}
|
||||
g_paddle_buttons = 0xc;
|
||||
|
||||
joystick_update(0.0);
|
||||
joystick_update(0.0);
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update(double dcycs)
|
||||
{
|
||||
JOYCAPS joycap;
|
||||
JOYINFO info;
|
||||
UINT id;
|
||||
MMRESULT ret1, ret2;
|
||||
void joystick_update(double dcycs) {
|
||||
JOYCAPS joycap;
|
||||
JOYINFO info;
|
||||
UINT id;
|
||||
MMRESULT ret1, ret2;
|
||||
|
||||
id = g_joystick_native_type;
|
||||
id = g_joystick_native_type;
|
||||
|
||||
ret1 = joyGetDevCaps(id, &joycap, sizeof(joycap));
|
||||
ret2 = joyGetPos(id, &info);
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 32768 /
|
||||
(joycap.wXmax - joycap.wXmin);
|
||||
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 32768 /
|
||||
(joycap.wYmax - joycap.wYmin);
|
||||
if(info.wButtons & JOY_BUTTON1) {
|
||||
g_paddle_buttons = g_paddle_buttons | 1;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~1);
|
||||
}
|
||||
if(info.wButtons & JOY_BUTTON2) {
|
||||
g_paddle_buttons = g_paddle_buttons | 2;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~2);
|
||||
}
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
}
|
||||
ret1 = joyGetDevCaps(id, &joycap, sizeof(joycap));
|
||||
ret2 = joyGetPos(id, &info);
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 32768 /
|
||||
(joycap.wXmax - joycap.wXmin);
|
||||
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 32768 /
|
||||
(joycap.wYmax - joycap.wYmin);
|
||||
if(info.wButtons & JOY_BUTTON1) {
|
||||
g_paddle_buttons = g_paddle_buttons | 1;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~1);
|
||||
}
|
||||
if(info.wButtons & JOY_BUTTON2) {
|
||||
g_paddle_buttons = g_paddle_buttons | 2;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~2);
|
||||
}
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_buttons()
|
||||
{
|
||||
JOYINFOEX info;
|
||||
UINT id;
|
||||
void joystick_update_buttons() {
|
||||
JOYINFOEX info;
|
||||
UINT id;
|
||||
|
||||
id = g_joystick_native_type;
|
||||
id = g_joystick_native_type;
|
||||
|
||||
info.dwSize = sizeof(JOYINFOEX);
|
||||
info.dwFlags = JOY_RETURNBUTTONS;
|
||||
if(joyGetPosEx(id, &info) == JOYERR_NOERROR) {
|
||||
if(info.dwButtons & JOY_BUTTON1) {
|
||||
g_paddle_buttons = g_paddle_buttons | 1;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~1);
|
||||
}
|
||||
if(info.dwButtons & JOY_BUTTON2) {
|
||||
g_paddle_buttons = g_paddle_buttons | 2;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~2);
|
||||
}
|
||||
}
|
||||
info.dwSize = sizeof(JOYINFOEX);
|
||||
info.dwFlags = JOY_RETURNBUTTONS;
|
||||
if(joyGetPosEx(id, &info) == JOYERR_NOERROR) {
|
||||
if(info.dwButtons & JOY_BUTTON1) {
|
||||
g_paddle_buttons = g_paddle_buttons | 1;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~1);
|
||||
}
|
||||
if(info.dwButtons & JOY_BUTTON2) {
|
||||
g_paddle_buttons = g_paddle_buttons | 2;
|
||||
} else {
|
||||
g_paddle_buttons = g_paddle_buttons & (~2);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -344,31 +326,24 @@ joystick_update_buttons()
|
|||
|
||||
#ifndef JOYSTICK_DEFINED
|
||||
/* stubs for the routines */
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
g_joystick_native_type1 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
g_joystick_native_type = -1;
|
||||
void joystick_init() {
|
||||
g_joystick_native_type1 = -1;
|
||||
g_joystick_native_type2 = -1;
|
||||
g_joystick_native_type = -1;
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update(double dcycs)
|
||||
{
|
||||
int i;
|
||||
void joystick_update(double dcycs) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 32767;
|
||||
}
|
||||
g_paddle_buttons = 0xc;
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 32767;
|
||||
}
|
||||
g_paddle_buttons = 0xc;
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_buttons()
|
||||
{
|
||||
void joystick_update_buttons() {
|
||||
}
|
||||
|
||||
void joystick_shut()
|
||||
{
|
||||
void joystick_shut() {
|
||||
}
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#ifdef ACTIVEIPHONE
|
||||
#include <CoreGraphics/CGContext.h>
|
||||
|
@ -21,30 +21,30 @@
|
|||
#include "protos_macdriver.h"
|
||||
|
||||
|
||||
word32 g_mac_shift_control_state = 0;
|
||||
word32 g_mac_shift_control_state = 0;
|
||||
int macUsingCoreGraphics=0;
|
||||
|
||||
// Coregraphics context
|
||||
|
||||
CGContextRef offscreenContext = NULL;
|
||||
CGContextRef offscreenContext = NULL;
|
||||
char * bitmapData=NULL;
|
||||
int bitmapByteCount;
|
||||
int bitmapBytesPerRow;
|
||||
int bitmapByteCount;
|
||||
int bitmapBytesPerRow;
|
||||
|
||||
#ifdef ENABLEQD
|
||||
WindowRef g_main_window;
|
||||
WindowRef g_main_window;
|
||||
CGrafPtr mac_window_port;
|
||||
#endif
|
||||
|
||||
char *g_clipboard = 0x00;
|
||||
int g_clipboard_pos;
|
||||
int g_clipboard_pos;
|
||||
|
||||
|
||||
|
||||
extern Kimage g_mainwin_kimage;
|
||||
|
||||
|
||||
int g_use_shmem = 0;
|
||||
int g_use_shmem = 0;
|
||||
|
||||
extern int Verbose;
|
||||
|
||||
|
@ -67,8 +67,8 @@ extern int g_send_sound_to_file;
|
|||
extern int g_config_control_panel;
|
||||
|
||||
|
||||
int g_auto_repeat_on = -1;
|
||||
int g_x_shift_control_state = 0;
|
||||
int g_auto_repeat_on = -1;
|
||||
int g_x_shift_control_state = 0;
|
||||
|
||||
|
||||
extern int Max_color_size;
|
||||
|
@ -76,8 +76,8 @@ extern int Max_color_size;
|
|||
extern word32 g_palette_8to1624[256];
|
||||
extern word32 g_a2palette_8to1624[256];
|
||||
|
||||
int g_alt_left_up = 1;
|
||||
int g_alt_right_up = 1;
|
||||
int g_alt_left_up = 1;
|
||||
int g_alt_right_up = 1;
|
||||
|
||||
extern word32 g_full_refresh_needed;
|
||||
|
||||
|
@ -100,442 +100,413 @@ int g_upd_count = 0;
|
|||
|
||||
|
||||
|
||||
void
|
||||
update_window(void)
|
||||
{
|
||||
|
||||
// OG Not needed
|
||||
/*
|
||||
SetPortWindowPort(g_main_window);
|
||||
PenNormal();
|
||||
*/
|
||||
|
||||
g_full_refresh_needed = -1;
|
||||
g_a2_screen_buffer_changed = -1;
|
||||
g_status_refresh_needed = 1;
|
||||
g_border_sides_refresh_needed = 1;
|
||||
g_border_special_refresh_needed = 1;
|
||||
void update_window(void) {
|
||||
|
||||
g_upd_count++;
|
||||
if(g_upd_count > 250) {
|
||||
g_upd_count = 0;
|
||||
}
|
||||
// OG Not needed
|
||||
/*
|
||||
SetPortWindowPort(g_main_window);
|
||||
PenNormal();
|
||||
*/
|
||||
|
||||
g_full_refresh_needed = -1;
|
||||
g_a2_screen_buffer_changed = -1;
|
||||
g_status_refresh_needed = 1;
|
||||
g_border_sides_refresh_needed = 1;
|
||||
g_border_special_refresh_needed = 1;
|
||||
|
||||
g_upd_count++;
|
||||
if(g_upd_count > 250) {
|
||||
g_upd_count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mac_update_modifiers(word32 state)
|
||||
{
|
||||
void mac_update_modifiers(word32 state) {
|
||||
#ifndef ACTIVEIPHONE
|
||||
|
||||
word32 state_xor;
|
||||
int is_up;
|
||||
word32 state_xor;
|
||||
int is_up;
|
||||
|
||||
state = state & (
|
||||
cmdKey | controlKey |
|
||||
shiftKey | alphaLock | optionKey
|
||||
);
|
||||
state_xor = g_mac_shift_control_state ^ state;
|
||||
is_up = 0;
|
||||
if(state_xor & controlKey) {
|
||||
is_up = ((state & controlKey) == 0);
|
||||
adb_physical_key_update(0x36, is_up);
|
||||
}
|
||||
if(state_xor & alphaLock) {
|
||||
is_up = ((state & alphaLock) == 0);
|
||||
adb_physical_key_update(0x39, is_up);
|
||||
}
|
||||
if(state_xor & shiftKey) {
|
||||
is_up = ((state & shiftKey) == 0);
|
||||
adb_physical_key_update(0x38, is_up);
|
||||
}
|
||||
if(state_xor & cmdKey) {
|
||||
is_up = ((state & cmdKey) == 0);
|
||||
adb_physical_key_update(0x37, is_up);
|
||||
}
|
||||
if(state_xor & optionKey) {
|
||||
is_up = ((state & optionKey) == 0);
|
||||
adb_physical_key_update(0x3a, is_up);
|
||||
}
|
||||
state = state & (
|
||||
cmdKey | controlKey |
|
||||
shiftKey | alphaLock | optionKey
|
||||
);
|
||||
state_xor = g_mac_shift_control_state ^ state;
|
||||
is_up = 0;
|
||||
if(state_xor & controlKey) {
|
||||
is_up = ((state & controlKey) == 0);
|
||||
adb_physical_key_update(0x36, is_up);
|
||||
}
|
||||
if(state_xor & alphaLock) {
|
||||
is_up = ((state & alphaLock) == 0);
|
||||
adb_physical_key_update(0x39, is_up);
|
||||
}
|
||||
if(state_xor & shiftKey) {
|
||||
is_up = ((state & shiftKey) == 0);
|
||||
adb_physical_key_update(0x38, is_up);
|
||||
}
|
||||
if(state_xor & cmdKey) {
|
||||
is_up = ((state & cmdKey) == 0);
|
||||
adb_physical_key_update(0x37, is_up);
|
||||
}
|
||||
if(state_xor & optionKey) {
|
||||
is_up = ((state & optionKey) == 0);
|
||||
adb_physical_key_update(0x3a, is_up);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_mac_shift_control_state = state;
|
||||
g_mac_shift_control_state = state;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
|
||||
{
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb) {
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_update_physical_colormap()
|
||||
{
|
||||
void x_update_physical_colormap() {
|
||||
}
|
||||
|
||||
void
|
||||
show_xcolor_array()
|
||||
{
|
||||
int i;
|
||||
void show_xcolor_array() {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
printf("%02x: %08x\n", i, g_palette_8to1624[i]);
|
||||
}
|
||||
for(i = 0; i < 256; i++) {
|
||||
printf("%02x: %08x\n", i, g_palette_8to1624[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
x_get_kimage(Kimage *kimage_ptr)
|
||||
{
|
||||
void x_get_kimage(Kimage *kimage_ptr) {
|
||||
#ifdef ENABLEQD
|
||||
PixMapHandle pixmap_handle;
|
||||
GWorldPtr world;
|
||||
Rect world_rect;
|
||||
OSStatus err;
|
||||
PixMapHandle pixmap_handle;
|
||||
GWorldPtr world;
|
||||
Rect world_rect;
|
||||
OSStatus err;
|
||||
#endif
|
||||
word32 *wptr;
|
||||
byte *ptr;
|
||||
int row_bytes;
|
||||
int width;
|
||||
int height;
|
||||
int depth, mdepth;
|
||||
int size;
|
||||
word32 *wptr;
|
||||
byte *ptr;
|
||||
int row_bytes;
|
||||
int width;
|
||||
int height;
|
||||
int depth, mdepth;
|
||||
int size;
|
||||
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
depth = kimage_ptr->depth;
|
||||
mdepth = kimage_ptr->mdepth;
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
depth = kimage_ptr->depth;
|
||||
mdepth = kimage_ptr->mdepth;
|
||||
|
||||
size = 0;
|
||||
if(depth == g_screen_depth)
|
||||
{
|
||||
size = 0;
|
||||
if(depth == g_screen_depth)
|
||||
{
|
||||
|
||||
if (!macUsingCoreGraphics)
|
||||
|
||||
{
|
||||
if (!macUsingCoreGraphics)
|
||||
|
||||
{
|
||||
#ifdef ENABLEQD
|
||||
SetRect(&world_rect, 0, 0, width, height);
|
||||
err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0);
|
||||
pixmap_handle = GetGWorldPixMap(world);
|
||||
err = LockPixels(pixmap_handle);
|
||||
ptr = (byte *)GetPixBaseAddr(pixmap_handle);
|
||||
row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff);
|
||||
kimage_ptr->width_act = row_bytes / (mdepth >> 3);
|
||||
mac_printf("Got depth: %d, bitmap_ptr: %p, width: %d\n", depth, ptr, kimage_ptr->width_act);
|
||||
mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",(int)(*pixmap_handle)->baseAddr,(*pixmap_handle)->rowBytes,(*pixmap_handle)->pixelType);
|
||||
wptr = (word32 *)(*pixmap_handle);
|
||||
mac_printf("wptr: %p=%08x %08x %08x %08x %08x %08x %08x %08x\n",wptr,wptr[0], wptr[1], wptr[2], wptr[3],wptr[4], wptr[5], wptr[6], wptr[7]);
|
||||
kimage_ptr->dev_handle = pixmap_handle;
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
SetRect(&world_rect, 0, 0, width, height);
|
||||
err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0);
|
||||
pixmap_handle = GetGWorldPixMap(world);
|
||||
err = LockPixels(pixmap_handle);
|
||||
ptr = (byte *)GetPixBaseAddr(pixmap_handle);
|
||||
row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff);
|
||||
kimage_ptr->width_act = row_bytes / (mdepth >> 3);
|
||||
mac_printf("Got depth: %d, bitmap_ptr: %p, width: %d\n", depth, ptr, kimage_ptr->width_act);
|
||||
mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",(int)(*pixmap_handle)->baseAddr,(*pixmap_handle)->rowBytes,(*pixmap_handle)->pixelType);
|
||||
wptr = (word32 *)(*pixmap_handle);
|
||||
mac_printf("wptr: %p=%08x %08x %08x %08x %08x %08x %08x %08x\n",wptr,wptr[0], wptr[1], wptr[2], wptr[3],wptr[4], wptr[5], wptr[6], wptr[7]);
|
||||
kimage_ptr->dev_handle = pixmap_handle;
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
kimage_ptr->width_act = width ;
|
||||
size = height* kimage_ptr->width_act * mdepth >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* allocate buffers for video.c to draw into */
|
||||
|
||||
|
||||
kimage_ptr->width_act = width ;
|
||||
size = height* kimage_ptr->width_act * mdepth >> 3 ;
|
||||
ptr = (byte *)malloc(size);
|
||||
kimage_ptr->width_act = width;
|
||||
size = height* kimage_ptr->width_act * mdepth >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
if(ptr == 0) {
|
||||
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
}
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr,
|
||||
kimage_ptr->dev_handle, kimage_ptr->data_ptr, size);
|
||||
/* allocate buffers for video.c to draw into */
|
||||
|
||||
|
||||
kimage_ptr->width_act = width;
|
||||
size = height* kimage_ptr->width_act * mdepth >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
}
|
||||
|
||||
mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr,
|
||||
kimage_ptr->dev_handle, kimage_ptr->data_ptr, size);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLEQD
|
||||
PixMapHandle pixmap_backbuffer=NULL;
|
||||
GWorldPtr backbuffer=NULL;
|
||||
PixMapHandle pixmap_backbuffer=NULL;
|
||||
GWorldPtr backbuffer=NULL;
|
||||
#endif
|
||||
|
||||
void
|
||||
dev_video_init()
|
||||
{
|
||||
int lores_col;
|
||||
int i;
|
||||
void dev_video_init() {
|
||||
int lores_col;
|
||||
int i;
|
||||
|
||||
printf("Preparing graphics system\n");
|
||||
|
||||
// OG Create backbuffer
|
||||
if (!macUsingCoreGraphics)
|
||||
{
|
||||
printf("Preparing graphics system\n");
|
||||
|
||||
// OG Create backbuffer
|
||||
if (!macUsingCoreGraphics)
|
||||
{
|
||||
|
||||
#ifdef ENABLEQD
|
||||
Rect r;
|
||||
SetRect(&r, 0, 0, 704, 462);
|
||||
QDErr err = NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0);
|
||||
pixmap_backbuffer = GetGWorldPixMap(backbuffer);
|
||||
Rect r;
|
||||
SetRect(&r, 0, 0, 704, 462);
|
||||
QDErr err = NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0);
|
||||
pixmap_backbuffer = GetGWorldPixMap(backbuffer);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
int pixelsWide = 704;
|
||||
int pixelsHigh = 462;
|
||||
bitmapBytesPerRow = (pixelsWide * 4);// 1
|
||||
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
bitmapData = (char*)malloc( bitmapByteCount );// 3
|
||||
if (bitmapData == NULL)
|
||||
{
|
||||
fprintf (stderr, "Memory not allocated!");
|
||||
return ;
|
||||
}
|
||||
offscreenContext = CGBitmapContextCreate (bitmapData,// 4
|
||||
pixelsWide,
|
||||
pixelsHigh,
|
||||
8, // bits per component
|
||||
bitmapBytesPerRow,
|
||||
colorSpace,
|
||||
kCGImageAlphaNoneSkipLast);
|
||||
if (offscreenContext== NULL)
|
||||
{
|
||||
free (bitmapData);// 5
|
||||
fprintf (stderr, "Context not created!");
|
||||
return ;
|
||||
}
|
||||
|
||||
CGContextSetRGBFillColor (offscreenContext, 1, 0.5, 0.5, 1);
|
||||
CGContextFillRect (offscreenContext, CGRectMake (0,0, 704, 462 ));
|
||||
|
||||
CGColorSpaceRelease( colorSpace );// 6
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
video_get_kimages();
|
||||
int pixelsWide = 704;
|
||||
int pixelsHigh = 462;
|
||||
bitmapBytesPerRow = (pixelsWide * 4); // 1
|
||||
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
|
||||
|
||||
if(g_screen_depth != 8) {
|
||||
// Get g_mainwin_kimage
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
|
||||
g_screen_mdepth);
|
||||
}
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
bitmapData = (char*)malloc( bitmapByteCount ); // 3
|
||||
if (bitmapData == NULL)
|
||||
{
|
||||
fprintf (stderr, "Memory not allocated!");
|
||||
return;
|
||||
}
|
||||
offscreenContext = CGBitmapContextCreate (bitmapData, // 4
|
||||
pixelsWide,
|
||||
pixelsHigh,
|
||||
8, // bits per component
|
||||
bitmapBytesPerRow,
|
||||
colorSpace,
|
||||
kCGImageAlphaNoneSkipLast);
|
||||
if (offscreenContext== NULL)
|
||||
{
|
||||
free (bitmapData); // 5
|
||||
fprintf (stderr, "Context not created!");
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
lores_col = g_lores_colors[i & 0xf];
|
||||
video_update_color_raw(i, lores_col);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
CGContextSetRGBFillColor (offscreenContext, 1, 0.5, 0.5, 1);
|
||||
CGContextFillRect (offscreenContext, CGRectMake (0,0, 704, 462 ));
|
||||
|
||||
g_installed_full_superhires_colormap = 1;
|
||||
CGColorSpaceRelease( colorSpace ); // 6
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
video_get_kimages();
|
||||
|
||||
if(g_screen_depth != 8) {
|
||||
// Get g_mainwin_kimage
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
|
||||
g_screen_mdepth);
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
lores_col = g_lores_colors[i & 0xf];
|
||||
video_update_color_raw(i, lores_col);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
|
||||
g_installed_full_superhires_colormap = 1;
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
|
||||
int width, int height)
|
||||
{
|
||||
int i;
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
|
||||
int width, int height) {
|
||||
int i;
|
||||
|
||||
if (!macUsingCoreGraphics)
|
||||
{
|
||||
if (!macUsingCoreGraphics)
|
||||
{
|
||||
#ifdef ENABLEQD
|
||||
PixMapHandle pixmap_handle;
|
||||
Rect src_rect, dest_rect;
|
||||
CGrafPtr window_port;
|
||||
PixMapHandle pixmap_handle;
|
||||
Rect src_rect, dest_rect;
|
||||
CGrafPtr window_port;
|
||||
|
||||
pixmap_handle = (PixMapHandle)kimage_ptr->dev_handle;
|
||||
SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height);
|
||||
SetRect(&dest_rect, destx, desty, destx + width, desty + height);
|
||||
pixmap_handle = (PixMapHandle)kimage_ptr->dev_handle;
|
||||
SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height);
|
||||
SetRect(&dest_rect, destx, desty, destx + width, desty + height);
|
||||
|
||||
#ifndef ACTIVEGSPLUGIN
|
||||
SetPortWindowPort(g_main_window);
|
||||
window_port = GetWindowPort(g_main_window);
|
||||
#ifndef ACTIVEGSPLUGIN
|
||||
SetPortWindowPort(g_main_window);
|
||||
window_port = GetWindowPort(g_main_window);
|
||||
|
||||
CopyBits( (BitMap *)(*pixmap_handle),
|
||||
GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect,
|
||||
srcCopy, NULL);
|
||||
CopyBits( (BitMap *)(*pixmap_handle),
|
||||
GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect,
|
||||
srcCopy, NULL);
|
||||
#else // !ACTIVEGSPLUGIN
|
||||
// OG Write to the back buffer instead of the display window
|
||||
window_port = mac_window_port ;
|
||||
SetGWorld(backbuffer,NULL);
|
||||
// OG Write to the back buffer instead of the display window
|
||||
window_port = mac_window_port;
|
||||
SetGWorld(backbuffer,NULL);
|
||||
|
||||
CopyBits( (BitMap *)(*pixmap_handle),
|
||||
GetPortBitMapForCopyBits(backbuffer), &src_rect, &dest_rect,
|
||||
srcCopy, NULL);
|
||||
CopyBits( (BitMap *)(*pixmap_handle),
|
||||
GetPortBitMapForCopyBits(backbuffer), &src_rect, &dest_rect,
|
||||
srcCopy, NULL);
|
||||
#endif // ACTIVEGSPLUGIN
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
int wd = kimage_ptr->width_act * kimage_ptr->mdepth>>3;
|
||||
int w = width *4;
|
||||
char* ptrdest = bitmapData + bitmapBytesPerRow*desty + destx*4;
|
||||
char* srcdest = (char*)kimage_ptr->data_ptr + wd*srcy + srcx*4;
|
||||
for(i=0;i<height;i+=1)
|
||||
{
|
||||
memcpy(ptrdest,srcdest,w);
|
||||
ptrdest += bitmapBytesPerRow;
|
||||
srcdest += wd;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
int wd = kimage_ptr->width_act * kimage_ptr->mdepth>>3;
|
||||
int w = width *4;
|
||||
char* ptrdest = bitmapData + bitmapBytesPerRow*desty + destx*4;
|
||||
char* srcdest = (char*)kimage_ptr->data_ptr + wd*srcy + srcx*4;
|
||||
for(i=0; i<height; i+=1)
|
||||
{
|
||||
memcpy(ptrdest,srcdest,w);
|
||||
ptrdest += bitmapBytesPerRow;
|
||||
srcdest += wd;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_auto_repeat_on(int must)
|
||||
{
|
||||
void x_auto_repeat_on(int must) {
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_off(int must)
|
||||
{
|
||||
void x_auto_repeat_off(int must) {
|
||||
}
|
||||
|
||||
void
|
||||
x_hide_pointer(int do_hide)
|
||||
{
|
||||
void x_hide_pointer(int do_hide) {
|
||||
#ifdef ENABLEQD
|
||||
if(do_hide) {
|
||||
HideCursor();
|
||||
} else {
|
||||
ShowCursor();
|
||||
}
|
||||
if(do_hide) {
|
||||
HideCursor();
|
||||
} else {
|
||||
ShowCursor();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
update_main_window_size()
|
||||
{
|
||||
void update_main_window_size() {
|
||||
#ifdef ENABLEQD
|
||||
Rect win_rect;
|
||||
int width, height;
|
||||
int left, excess_height;
|
||||
int top, bottom;
|
||||
|
||||
GetPortBounds(GetWindowPort(g_main_window), &win_rect);
|
||||
width = win_rect.right - win_rect.left;
|
||||
height = win_rect.bottom - win_rect.top;
|
||||
g_video_act_width = width;
|
||||
g_video_act_height = height;
|
||||
|
||||
left = MAX(0, (width - A2_WINDOW_WIDTH) / 2);
|
||||
left = MIN(left, BASE_MARGIN_LEFT);
|
||||
g_video_act_margin_left = left;
|
||||
g_video_act_margin_right = left;
|
||||
|
||||
|
||||
excess_height = (height - A2_WINDOW_HEIGHT) / 2;
|
||||
bottom = MAX(0, excess_height / 2); // No less than 0
|
||||
bottom = MIN(BASE_MARGIN_BOTTOM, bottom); // No more than 30
|
||||
g_video_act_margin_bottom = bottom;
|
||||
excess_height -= bottom;
|
||||
top = MAX(0, excess_height);
|
||||
top = MIN(BASE_MARGIN_TOP, top);
|
||||
g_video_act_margin_top = top;
|
||||
Rect win_rect;
|
||||
int width, height;
|
||||
int left, excess_height;
|
||||
int top, bottom;
|
||||
|
||||
GetPortBounds(GetWindowPort(g_main_window), &win_rect);
|
||||
width = win_rect.right - win_rect.left;
|
||||
height = win_rect.bottom - win_rect.top;
|
||||
g_video_act_width = width;
|
||||
g_video_act_height = height;
|
||||
|
||||
left = MAX(0, (width - A2_WINDOW_WIDTH) / 2);
|
||||
left = MIN(left, BASE_MARGIN_LEFT);
|
||||
g_video_act_margin_left = left;
|
||||
g_video_act_margin_right = left;
|
||||
|
||||
|
||||
excess_height = (height - A2_WINDOW_HEIGHT) / 2;
|
||||
bottom = MAX(0, excess_height / 2); // No less than 0
|
||||
bottom = MIN(BASE_MARGIN_BOTTOM, bottom); // No more than 30
|
||||
g_video_act_margin_bottom = bottom;
|
||||
excess_height -= bottom;
|
||||
top = MAX(0, excess_height);
|
||||
top = MIN(BASE_MARGIN_TOP, top);
|
||||
g_video_act_margin_top = top;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// OG Adding release
|
||||
void x_release_kimage(Kimage* kimage_ptr)
|
||||
{
|
||||
if (kimage_ptr->dev_handle == (void*)-1)
|
||||
{
|
||||
free(kimage_ptr->data_ptr);
|
||||
kimage_ptr->data_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!macUsingCoreGraphics)
|
||||
{
|
||||
void x_release_kimage(Kimage* kimage_ptr) {
|
||||
if (kimage_ptr->dev_handle == (void*)-1)
|
||||
{
|
||||
free(kimage_ptr->data_ptr);
|
||||
kimage_ptr->data_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!macUsingCoreGraphics)
|
||||
{
|
||||
#ifdef ENABLEQD
|
||||
UnlockPixels((PixMapHandle)kimage_ptr->dev_handle);
|
||||
kimage_ptr->dev_handle = NULL;
|
||||
DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2);
|
||||
kimage_ptr->dev_handle2 = NULL;
|
||||
UnlockPixels((PixMapHandle)kimage_ptr->dev_handle);
|
||||
kimage_ptr->dev_handle = NULL;
|
||||
DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2);
|
||||
kimage_ptr->dev_handle2 = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OG Addding ratio
|
||||
int x_calc_ratio(float x,float y)
|
||||
{
|
||||
return 1;
|
||||
int x_calc_ratio(float x,float y) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
clipboard_paste(void)
|
||||
{
|
||||
void clipboard_paste(void) {
|
||||
#define CHUNK_SIZE 1024
|
||||
char buffer[CHUNK_SIZE];
|
||||
int bufsize = 1;
|
||||
void *expanding_buffer = 0x00;
|
||||
if (g_clipboard)
|
||||
{
|
||||
g_clipboard_pos = 0;
|
||||
free(g_clipboard);
|
||||
g_clipboard = 0x00;
|
||||
}
|
||||
FILE *pipe = popen("pbpaste", "r");
|
||||
if (pipe)
|
||||
{
|
||||
expanding_buffer = calloc(CHUNK_SIZE+1,1);
|
||||
bufsize = CHUNK_SIZE;
|
||||
while (!feof(pipe))
|
||||
{
|
||||
if (fgets(buffer, CHUNK_SIZE, pipe) != NULL)
|
||||
{
|
||||
while (strlen((char*)expanding_buffer) + strlen(buffer) > bufsize)
|
||||
{
|
||||
bufsize += CHUNK_SIZE + 1;
|
||||
expanding_buffer = realloc(expanding_buffer, bufsize);
|
||||
}
|
||||
/* Skip the leading return character when this is the first line in the paste buffer */
|
||||
if (strlen((char*)expanding_buffer) > 0)
|
||||
strcat((char*)expanding_buffer,"\r");
|
||||
strncat((char*)expanding_buffer,buffer,strlen(buffer));
|
||||
g_clipboard = (char*)expanding_buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
char buffer[CHUNK_SIZE];
|
||||
int bufsize = 1;
|
||||
void *expanding_buffer = 0x00;
|
||||
if (g_clipboard)
|
||||
{
|
||||
g_clipboard_pos = 0;
|
||||
free(g_clipboard);
|
||||
g_clipboard = 0x00;
|
||||
}
|
||||
FILE *pipe = popen("pbpaste", "r");
|
||||
if (pipe)
|
||||
{
|
||||
expanding_buffer = calloc(CHUNK_SIZE+1,1);
|
||||
bufsize = CHUNK_SIZE;
|
||||
while (!feof(pipe))
|
||||
{
|
||||
if (fgets(buffer, CHUNK_SIZE, pipe) != NULL)
|
||||
{
|
||||
while (strlen((char*)expanding_buffer) + strlen(buffer) > bufsize)
|
||||
{
|
||||
bufsize += CHUNK_SIZE + 1;
|
||||
expanding_buffer = realloc(expanding_buffer, bufsize);
|
||||
}
|
||||
/* Skip the leading return character when this is the first line in the paste buffer */
|
||||
if (strlen((char*)expanding_buffer) > 0)
|
||||
strcat((char*)expanding_buffer,"\r");
|
||||
strncat((char*)expanding_buffer,buffer,strlen(buffer));
|
||||
g_clipboard = (char*)expanding_buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int clipboard_get_char(void)
|
||||
{
|
||||
if (!g_clipboard)
|
||||
return 0;
|
||||
if (g_clipboard[g_clipboard_pos] == '\n')
|
||||
g_clipboard_pos++;
|
||||
if (g_clipboard[g_clipboard_pos] == '\0')
|
||||
return 0;
|
||||
return g_clipboard[g_clipboard_pos++] | 0x80;
|
||||
int clipboard_get_char(void) {
|
||||
if (!g_clipboard)
|
||||
return 0;
|
||||
if (g_clipboard[g_clipboard_pos] == '\n')
|
||||
g_clipboard_pos++;
|
||||
if (g_clipboard[g_clipboard_pos] == '\0')
|
||||
return 0;
|
||||
return g_clipboard[g_clipboard_pos++] | 0x80;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
|
||||
|
@ -19,11 +19,11 @@ int mac_send_audio(byte *ptr, int in_size) {}
|
|||
#include "sound.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#define MACSND_REBUF_SIZE (64*1024)
|
||||
#define MACSND_QUANTA 512
|
||||
#define MACSND_REBUF_SIZE (64*1024)
|
||||
#define MACSND_QUANTA 512
|
||||
/* MACSND_QUANTA must be >= 128 and a power of 2 */
|
||||
|
||||
word32 g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
word32 g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
volatile word32 *g_macsnd_rebuf_ptr;
|
||||
volatile word32 *g_macsnd_rebuf_cur;
|
||||
volatile int g_macsnd_playing = 0;
|
||||
|
@ -35,124 +35,116 @@ extern word32 *g_sound_shm_addr;
|
|||
extern int g_sound_size;
|
||||
|
||||
|
||||
SndChannelPtr g_snd_channel_ptr;
|
||||
ExtSoundHeader g_snd_hdr;
|
||||
SndCommand g_snd_cmd;
|
||||
SndChannelPtr g_snd_channel_ptr;
|
||||
ExtSoundHeader g_snd_hdr;
|
||||
SndCommand g_snd_cmd;
|
||||
|
||||
void
|
||||
mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd)
|
||||
{
|
||||
OSStatus err;
|
||||
int samps;
|
||||
void mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd) {
|
||||
OSStatus err;
|
||||
int samps;
|
||||
|
||||
// This is an interrupt routine--no printf, etc!
|
||||
// This is an interrupt routine--no printf, etc!
|
||||
|
||||
samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur;
|
||||
if(samps < 0) {
|
||||
samps += MACSND_REBUF_SIZE;
|
||||
}
|
||||
samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur;
|
||||
if(samps < 0) {
|
||||
samps += MACSND_REBUF_SIZE;
|
||||
}
|
||||
|
||||
samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples
|
||||
if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) -
|
||||
g_macsnd_rebuf_cur;
|
||||
}
|
||||
if(samps > 0) {
|
||||
g_macsnd_playing = 1;
|
||||
g_snd_hdr.numFrames = samps;
|
||||
g_snd_hdr.loopEnd = samps;
|
||||
g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur; // OG Cast from byte* to ,char*
|
||||
samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples
|
||||
if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) -
|
||||
g_macsnd_rebuf_cur;
|
||||
}
|
||||
if(samps > 0) {
|
||||
g_macsnd_playing = 1;
|
||||
g_snd_hdr.numFrames = samps;
|
||||
g_snd_hdr.loopEnd = samps;
|
||||
g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur; // OG Cast from byte* to ,char*
|
||||
|
||||
g_snd_cmd.cmd = bufferCmd;
|
||||
g_snd_cmd.param1 = 0;
|
||||
g_snd_cmd.param2 = (long) &g_snd_hdr;
|
||||
g_snd_cmd.cmd = bufferCmd;
|
||||
g_snd_cmd.param1 = 0;
|
||||
g_snd_cmd.param2 = (long) &g_snd_hdr;
|
||||
|
||||
g_macsnd_rebuf_cur += samps;
|
||||
if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE;
|
||||
}
|
||||
g_macsnd_rebuf_cur += samps;
|
||||
if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE;
|
||||
}
|
||||
|
||||
err = SndDoImmediate(g_snd_channel_ptr, &g_snd_cmd);
|
||||
err = SndDoImmediate(g_snd_channel_ptr, &g_snd_cmd);
|
||||
|
||||
// And set-up callback
|
||||
g_snd_cmd.cmd = callBackCmd;
|
||||
g_snd_cmd.param1 = 0;
|
||||
g_snd_cmd.param2 = 0;
|
||||
err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE);
|
||||
} else {
|
||||
g_macsnd_playing = 0;
|
||||
}
|
||||
// And set-up callback
|
||||
g_snd_cmd.cmd = callBackCmd;
|
||||
g_snd_cmd.param1 = 0;
|
||||
g_snd_cmd.param2 = 0;
|
||||
err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE);
|
||||
} else {
|
||||
g_macsnd_playing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mac_send_audio(byte *ptr, int in_size)
|
||||
{
|
||||
SndCommand snd_cmd = {0};
|
||||
word32 *wptr, *macptr;
|
||||
word32 *eptr;
|
||||
int samps;
|
||||
int i;
|
||||
int mac_send_audio(byte *ptr, int in_size) {
|
||||
SndCommand snd_cmd = {0};
|
||||
word32 *wptr, *macptr;
|
||||
word32 *eptr;
|
||||
int samps;
|
||||
int i;
|
||||
|
||||
samps = in_size / 4;
|
||||
wptr = (word32 *)ptr;
|
||||
macptr = (word32 *)g_macsnd_rebuf_ptr;
|
||||
eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
for(i = 0; i < samps; i++) {
|
||||
*macptr++ = *wptr++;
|
||||
if(macptr >= eptr) {
|
||||
macptr = &g_macsnd_rebuf[0];
|
||||
}
|
||||
}
|
||||
samps = in_size / 4;
|
||||
wptr = (word32 *)ptr;
|
||||
macptr = (word32 *)g_macsnd_rebuf_ptr;
|
||||
eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
for(i = 0; i < samps; i++) {
|
||||
*macptr++ = *wptr++;
|
||||
if(macptr >= eptr) {
|
||||
macptr = &g_macsnd_rebuf[0];
|
||||
}
|
||||
}
|
||||
|
||||
g_macsnd_rebuf_ptr = macptr;
|
||||
g_macsnd_rebuf_ptr = macptr;
|
||||
|
||||
if(!g_macsnd_playing) {
|
||||
mac_snd_callback(g_snd_channel_ptr, &snd_cmd);
|
||||
}
|
||||
if(!g_macsnd_playing) {
|
||||
mac_snd_callback(g_snd_channel_ptr, &snd_cmd);
|
||||
}
|
||||
|
||||
return in_size;
|
||||
return in_size;
|
||||
}
|
||||
|
||||
void
|
||||
child_sound_init_mac()
|
||||
{
|
||||
OSStatus err;
|
||||
void child_sound_init_mac() {
|
||||
OSStatus err;
|
||||
|
||||
mac_printf("In mac child\n");
|
||||
fflush(stdout);
|
||||
mac_printf("pid: %d\n", getpid());
|
||||
fflush(stdout);
|
||||
mac_printf("In mac child\n");
|
||||
fflush(stdout);
|
||||
mac_printf("pid: %d\n", getpid());
|
||||
fflush(stdout);
|
||||
|
||||
//return;
|
||||
//return;
|
||||
|
||||
//g_snd_channel_ptr = 0;
|
||||
err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo,
|
||||
NewSndCallBackUPP(mac_snd_callback));
|
||||
mac_printf("SndNewChannel ret: %d\n", (int)err);
|
||||
fflush(stdout);
|
||||
//g_snd_channel_ptr = 0;
|
||||
err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo,
|
||||
NewSndCallBackUPP(mac_snd_callback));
|
||||
mac_printf("SndNewChannel ret: %d\n", (int)err);
|
||||
fflush(stdout);
|
||||
|
||||
memset(&g_snd_hdr, 0, sizeof(g_snd_hdr));
|
||||
g_snd_hdr.sampleSize = 16;
|
||||
g_snd_hdr.numChannels = 2;
|
||||
g_audio_rate = 44100;
|
||||
g_snd_hdr.sampleRate = g_audio_rate << 16;
|
||||
g_snd_hdr.numFrames = 0; // will be set in mac_send_audio
|
||||
g_snd_hdr.encode = extSH;
|
||||
g_snd_hdr.baseFrequency = 0;
|
||||
g_snd_hdr.samplePtr = 0;
|
||||
memset(&g_snd_hdr, 0, sizeof(g_snd_hdr));
|
||||
g_snd_hdr.sampleSize = 16;
|
||||
g_snd_hdr.numChannels = 2;
|
||||
g_audio_rate = 44100;
|
||||
g_snd_hdr.sampleRate = g_audio_rate << 16;
|
||||
g_snd_hdr.numFrames = 0; // will be set in mac_send_audio
|
||||
g_snd_hdr.encode = extSH;
|
||||
g_snd_hdr.baseFrequency = 0;
|
||||
g_snd_hdr.samplePtr = 0;
|
||||
|
||||
set_audio_rate(g_audio_rate);
|
||||
set_audio_rate(g_audio_rate);
|
||||
|
||||
mac_printf("End of child_sound_init_mac\n");
|
||||
fflush(stdout);
|
||||
mac_printf("End of child_sound_init_mac\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
macsnd_init(word32 *shmaddr)
|
||||
{
|
||||
g_macsnd_rebuf_cur = &g_macsnd_rebuf[0];
|
||||
g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0];
|
||||
mac_printf("macsnd_init called\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
void macsnd_init(word32 *shmaddr) {
|
||||
g_macsnd_rebuf_cur = &g_macsnd_rebuf[0];
|
||||
g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0];
|
||||
mac_printf("macsnd_init called\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
}
|
||||
#endif
|
||||
|
|
4429
src/moremem.c
4429
src/moremem.c
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,10 @@
|
|||
|
||||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@ -11,9 +17,9 @@
|
|||
|
||||
// Halts on bad reads. Sets flags via engine_s.s:set_halt_act() function
|
||||
extern int g_halt_on_bad_read; // defined in sim65816.c
|
||||
// Ignore bad memory accesses.
|
||||
// Ignore bad memory accesses.
|
||||
extern int g_ignore_bad_acc; // defined in sim65816.c
|
||||
// Ignore red alert halts.
|
||||
// Ignore red alert halts.
|
||||
extern int g_ignore_halts; // defined in sim65816.c
|
||||
// Size of RAM memory expansion card in bytes (default = 8*1024*1024 = 8MB)
|
||||
extern int g_mem_size_exp; // defined in sim65816.c
|
||||
|
@ -41,7 +47,7 @@ extern int g_ethernet; // defined in sim65816.c
|
|||
extern int g_dbg_enable_port; // defined in debug.c
|
||||
// Set preferred audio frequency
|
||||
extern int g_preferred_rate; // defined in sound_driver.c, implemented in various driver files
|
||||
// Enable/disable audio
|
||||
// Enable/disable audio
|
||||
extern int g_audio_enable; // defined in sound.c
|
||||
// Start in fullscreen mode
|
||||
extern int g_fullscreen; // defined in adb.c, because weird driver writing for x
|
||||
|
@ -102,7 +108,7 @@ int parse_int(const char *str1, int min, int max)
|
|||
printf ( "TMP %d\n", tmp);
|
||||
return tmp;
|
||||
}
|
||||
int parse_cli_options(int argc, char **argv) {
|
||||
int parse_cli_options(int argc, char **argv) {
|
||||
int i;
|
||||
int tmp1;
|
||||
int skip_amt;
|
||||
|
@ -206,7 +212,7 @@ int parse_cli_options(int argc, char **argv) {
|
|||
tmp1 = strtol(argv[i+1], 0, 0); // no bounds check, not sure what ids we get
|
||||
glogf("%s Setting joystick X axis %d", parse_log_prefix, tmp1);
|
||||
g_joystick_x_axis = tmp1;
|
||||
i++;
|
||||
i++;
|
||||
} else if(!strcmp("-joy_y", argv[i])) {
|
||||
if((i+1) >= argc) {
|
||||
glogf("%s Error, option '-joy_y' missing argument", parse_log_prefix);
|
||||
|
@ -224,7 +230,7 @@ int parse_cli_options(int argc, char **argv) {
|
|||
tmp1 = strtol(argv[i+1], 0, 0); // no bounds check, not sure what ids we get
|
||||
glogf("%s Setting joystick X2 axis %d", parse_log_prefix, tmp1);
|
||||
g_joystick_x2_axis = tmp1;
|
||||
i++;
|
||||
i++;
|
||||
} else if(!strcmp("-joy_y2", argv[i])) {
|
||||
if((i+1) >= argc) {
|
||||
glogf("%s Error, option '-joy_y2' missing argument", parse_log_prefix);
|
||||
|
|
284
src/paddles.c
284
src/paddles.c
|
@ -1,189 +1,175 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
|
||||
extern int g_mouse_raw_x; /* from adb.c */
|
||||
extern int g_mouse_raw_x; /* from adb.c */
|
||||
extern int g_mouse_raw_y;
|
||||
|
||||
double g_paddle_trig_dcycs = 0.0;
|
||||
int g_swap_paddles = 0;
|
||||
int g_invert_paddles = 0;
|
||||
int g_joystick_scale_factor_x = 0x100;
|
||||
int g_joystick_scale_factor_y = 0x100;
|
||||
int g_joystick_trim_amount_x = 0;
|
||||
int g_joystick_trim_amount_y = 0;
|
||||
double g_paddle_trig_dcycs = 0.0;
|
||||
int g_swap_paddles = 0;
|
||||
int g_invert_paddles = 0;
|
||||
int g_joystick_scale_factor_x = 0x100;
|
||||
int g_joystick_scale_factor_y = 0x100;
|
||||
int g_joystick_trim_amount_x = 0;
|
||||
int g_joystick_trim_amount_y = 0;
|
||||
|
||||
int g_joystick_type = JOYSTICK_TYPE_NATIVE_1; // OG Trying to set native joystick as default
|
||||
int g_joystick_native_type1 = -1;
|
||||
int g_joystick_native_type2 = -1;
|
||||
int g_joystick_native_type = -1;
|
||||
int g_joystick_type = JOYSTICK_TYPE_NATIVE_1; // OG Trying to set native joystick as default
|
||||
int g_joystick_native_type1 = -1;
|
||||
int g_joystick_native_type2 = -1;
|
||||
int g_joystick_native_type = -1;
|
||||
|
||||
extern int g_paddle_buttons;
|
||||
|
||||
int g_paddle_val[4] = { 0, 0, 0, 0 };
|
||||
/* g_paddle_val[0]: Joystick X coord, [1]:Y coord */
|
||||
int g_paddle_val[4] = { 0, 0, 0, 0 };
|
||||
/* g_paddle_val[0]: Joystick X coord, [1]:Y coord */
|
||||
|
||||
double g_paddle_dcycs[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
/* g_paddle_dcycs are the dcycs the paddle goes to 0 */
|
||||
double g_paddle_dcycs[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
/* g_paddle_dcycs are the dcycs the paddle goes to 0 */
|
||||
|
||||
|
||||
void
|
||||
paddle_fixup_joystick_type()
|
||||
{
|
||||
/* If g_joystick_type points to an illegal value, change it */
|
||||
if(g_joystick_type == JOYSTICK_TYPE_NATIVE_1) {
|
||||
g_joystick_native_type = g_joystick_native_type1;
|
||||
if(g_joystick_native_type1 < 0) {
|
||||
g_joystick_type = JOYSTICK_TYPE_KEYPAD;
|
||||
printf("no joy 1 --- switching to keypad\n");
|
||||
}
|
||||
}
|
||||
if(g_joystick_type == JOYSTICK_TYPE_NATIVE_2) {
|
||||
g_joystick_native_type = g_joystick_native_type2;
|
||||
if(g_joystick_native_type2 < 0) {
|
||||
g_joystick_type = JOYSTICK_TYPE_KEYPAD;
|
||||
printf("no joy 2 --- switching to keypad\n");
|
||||
}
|
||||
}
|
||||
void paddle_fixup_joystick_type() {
|
||||
/* If g_joystick_type points to an illegal value, change it */
|
||||
if(g_joystick_type == JOYSTICK_TYPE_NATIVE_1) {
|
||||
g_joystick_native_type = g_joystick_native_type1;
|
||||
if(g_joystick_native_type1 < 0) {
|
||||
g_joystick_type = JOYSTICK_TYPE_KEYPAD;
|
||||
printf("no joy 1 --- switching to keypad\n");
|
||||
}
|
||||
}
|
||||
if(g_joystick_type == JOYSTICK_TYPE_NATIVE_2) {
|
||||
g_joystick_native_type = g_joystick_native_type2;
|
||||
if(g_joystick_native_type2 < 0) {
|
||||
g_joystick_type = JOYSTICK_TYPE_KEYPAD;
|
||||
printf("no joy 2 --- switching to keypad\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
paddle_trigger(double dcycs)
|
||||
{
|
||||
/* Called by read/write to $c070 */
|
||||
g_paddle_trig_dcycs = dcycs;
|
||||
void paddle_trigger(double dcycs) {
|
||||
/* Called by read/write to $c070 */
|
||||
g_paddle_trig_dcycs = dcycs;
|
||||
|
||||
/* Determine what all the paddle values are right now */
|
||||
paddle_fixup_joystick_type();
|
||||
/* Determine what all the paddle values are right now */
|
||||
paddle_fixup_joystick_type();
|
||||
|
||||
switch(g_joystick_type) {
|
||||
case JOYSTICK_TYPE_KEYPAD: /* Keypad Joystick */
|
||||
paddle_trigger_keypad(dcycs);
|
||||
break;
|
||||
case JOYSTICK_TYPE_MOUSE: /* Mouse Joystick */
|
||||
paddle_trigger_mouse(dcycs);
|
||||
break;
|
||||
case JOYSTICK_TYPE_NONE: /* Mouse Joystick */
|
||||
paddle_trigger_mouse(dcycs);
|
||||
break;
|
||||
default:
|
||||
joystick_update(dcycs);
|
||||
}
|
||||
switch(g_joystick_type) {
|
||||
case JOYSTICK_TYPE_KEYPAD: /* Keypad Joystick */
|
||||
paddle_trigger_keypad(dcycs);
|
||||
break;
|
||||
case JOYSTICK_TYPE_MOUSE: /* Mouse Joystick */
|
||||
paddle_trigger_mouse(dcycs);
|
||||
break;
|
||||
case JOYSTICK_TYPE_NONE: /* Mouse Joystick */
|
||||
paddle_trigger_mouse(dcycs);
|
||||
break;
|
||||
default:
|
||||
joystick_update(dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
paddle_trigger_mouse(double dcycs)
|
||||
{
|
||||
int val_x, val_y;
|
||||
int mouse_x, mouse_y;
|
||||
void paddle_trigger_mouse(double dcycs) {
|
||||
int val_x, val_y;
|
||||
int mouse_x, mouse_y;
|
||||
|
||||
val_x = 0;
|
||||
val_x = 0;
|
||||
|
||||
mouse_x = g_mouse_raw_x;
|
||||
mouse_y = g_mouse_raw_y;
|
||||
/* mous_phys_x is 0->560, convert that to -32768 to + 32767 cyc */
|
||||
/* So subtract 280 then mult by 117 */
|
||||
val_x = (mouse_x - 280) * 117;
|
||||
mouse_x = g_mouse_raw_x;
|
||||
mouse_y = g_mouse_raw_y;
|
||||
/* mous_phys_x is 0->560, convert that to -32768 to + 32767 cyc */
|
||||
/* So subtract 280 then mult by 117 */
|
||||
val_x = (mouse_x - 280) * 117;
|
||||
|
||||
/* mous_phys_y is 0->384, convert that to -32768 to + 32767 cyc */
|
||||
/* so subtract 192 then mult by 180 to overscale it a bit */
|
||||
val_y = (mouse_y - 192) * 180;
|
||||
/* mous_phys_y is 0->384, convert that to -32768 to + 32767 cyc */
|
||||
/* so subtract 192 then mult by 180 to overscale it a bit */
|
||||
val_y = (mouse_y - 192) * 180;
|
||||
|
||||
g_paddle_val[0] = val_x;
|
||||
g_paddle_val[1] = val_y;
|
||||
g_paddle_val[2] = 32767;
|
||||
g_paddle_val[3] = 32767;
|
||||
g_paddle_buttons |= 0xc;
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
g_paddle_val[0] = val_x;
|
||||
g_paddle_val[1] = val_y;
|
||||
g_paddle_val[2] = 32767;
|
||||
g_paddle_val[3] = 32767;
|
||||
g_paddle_buttons |= 0xc;
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
}
|
||||
|
||||
void
|
||||
paddle_trigger_keypad(double dcycs)
|
||||
{
|
||||
int get_y;
|
||||
int val_x, val_y;
|
||||
void paddle_trigger_keypad(double dcycs) {
|
||||
int get_y;
|
||||
int val_x, val_y;
|
||||
|
||||
|
||||
val_x = adb_get_keypad_xy(get_y=0);
|
||||
val_y = adb_get_keypad_xy(get_y=1);
|
||||
/* val_x and val_y are already scale -32768 to +32768 */
|
||||
val_x = adb_get_keypad_xy(get_y=0);
|
||||
val_y = adb_get_keypad_xy(get_y=1);
|
||||
/* val_x and val_y are already scale -32768 to +32768 */
|
||||
|
||||
g_paddle_val[0] = val_x;
|
||||
g_paddle_val[1] = val_y;
|
||||
g_paddle_val[2] = 32767;
|
||||
g_paddle_val[3] = 32767;
|
||||
g_paddle_buttons |= 0xc;
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
g_paddle_val[0] = val_x;
|
||||
g_paddle_val[1] = val_y;
|
||||
g_paddle_val[2] = 32767;
|
||||
g_paddle_val[3] = 32767;
|
||||
g_paddle_buttons |= 0xc;
|
||||
paddle_update_trigger_dcycs(dcycs);
|
||||
}
|
||||
|
||||
void
|
||||
paddle_update_trigger_dcycs(double dcycs)
|
||||
{
|
||||
double trig_dcycs;
|
||||
int val;
|
||||
int paddle_num;
|
||||
int scale, trim;
|
||||
int i;
|
||||
void paddle_update_trigger_dcycs(double dcycs) {
|
||||
double trig_dcycs;
|
||||
int val;
|
||||
int paddle_num;
|
||||
int scale, trim;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
paddle_num = i;
|
||||
if(g_swap_paddles) {
|
||||
paddle_num = i ^ 1;
|
||||
}
|
||||
val = g_paddle_val[paddle_num];
|
||||
if(g_invert_paddles) {
|
||||
val = -val;
|
||||
}
|
||||
/* convert -32768 to +32768 into 0->2816.0 cycles (the */
|
||||
/* paddle delay const) */
|
||||
/* First multiply by the scale factor to adjust range */
|
||||
if(paddle_num & 1) {
|
||||
scale = g_joystick_scale_factor_y;
|
||||
trim = g_joystick_trim_amount_y;
|
||||
} else {
|
||||
scale = g_joystick_scale_factor_x;
|
||||
trim = g_joystick_trim_amount_x;
|
||||
}
|
||||
for(i = 0; i < 4; i++) {
|
||||
paddle_num = i;
|
||||
if(g_swap_paddles) {
|
||||
paddle_num = i ^ 1;
|
||||
}
|
||||
val = g_paddle_val[paddle_num];
|
||||
if(g_invert_paddles) {
|
||||
val = -val;
|
||||
}
|
||||
/* convert -32768 to +32768 into 0->2816.0 cycles (the */
|
||||
/* paddle delay const) */
|
||||
/* First multiply by the scale factor to adjust range */
|
||||
if(paddle_num & 1) {
|
||||
scale = g_joystick_scale_factor_y;
|
||||
trim = g_joystick_trim_amount_y;
|
||||
} else {
|
||||
scale = g_joystick_scale_factor_x;
|
||||
trim = g_joystick_trim_amount_x;
|
||||
}
|
||||
#if 0
|
||||
if(i == 0) {
|
||||
printf("val was %04x(%d) * scale %03x = %d\n",
|
||||
val, val, scale, (val*scale)>>16);
|
||||
}
|
||||
if(i == 0) {
|
||||
printf("val was %04x(%d) * scale %03x = %d\n",
|
||||
val, val, scale, (val*scale)>>16);
|
||||
}
|
||||
#endif
|
||||
val = val * scale >> 16;
|
||||
/* Val is now from -128 to + 128 since scale is */
|
||||
/* 256=1.0, 128 = 0.5 */
|
||||
val = val + 128 + trim;
|
||||
if(val >= 255) {
|
||||
val = 280; /* increase range */
|
||||
}
|
||||
trig_dcycs = dcycs + (val * 11.04);
|
||||
g_paddle_dcycs[i] = trig_dcycs;
|
||||
}
|
||||
val = val * scale >> 16;
|
||||
/* Val is now from -128 to + 128 since scale is */
|
||||
/* 256=1.0, 128 = 0.5 */
|
||||
val = val + 128 + trim;
|
||||
if(val >= 255) {
|
||||
val = 280; /* increase range */
|
||||
}
|
||||
trig_dcycs = dcycs + (val * 11.04);
|
||||
g_paddle_dcycs[i] = trig_dcycs;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
read_paddles(double dcycs, int paddle)
|
||||
{
|
||||
double trig_dcycs;
|
||||
int read_paddles(double dcycs, int paddle) {
|
||||
double trig_dcycs;
|
||||
|
||||
trig_dcycs = g_paddle_dcycs[paddle & 3];
|
||||
trig_dcycs = g_paddle_dcycs[paddle & 3];
|
||||
|
||||
if(dcycs < trig_dcycs) {
|
||||
return 0x80;
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
if(dcycs < trig_dcycs) {
|
||||
return 0x80;
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
paddle_update_buttons()
|
||||
{
|
||||
paddle_fixup_joystick_type();
|
||||
joystick_update_buttons();
|
||||
void paddle_update_buttons() {
|
||||
paddle_fixup_joystick_type();
|
||||
joystick_update_buttons();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/*
|
||||
parallel.c
|
||||
|
||||
This file handles the Apple II Parallel Card emulation in slot 1. Its very
|
||||
basic, but allows for future support of redirecting the output to a real
|
||||
parallel port, files, and additional types of emulated printers.
|
||||
*/
|
||||
This file handles the Apple II Parallel Card emulation in slot 1. Its very
|
||||
basic, but allows for future support of redirecting the output to a real
|
||||
parallel port, files, and additional types of emulated printers.
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include "printer.h"
|
||||
|
@ -21,42 +19,40 @@ extern int g_printer_timeout;
|
|||
word32 printer_vbl_count = 0;
|
||||
int port_block = 0;
|
||||
|
||||
byte parallel_read(word16 io_address)
|
||||
{
|
||||
//printf("parallel card status called at %x\n", io_address);
|
||||
//since we only have a virtual printer, always return state as "Ready"
|
||||
return 0xff;
|
||||
byte parallel_read(word16 io_address) {
|
||||
//printf("parallel card status called at %x\n", io_address);
|
||||
//since we only have a virtual printer, always return state as "Ready"
|
||||
return 0xff;
|
||||
}
|
||||
void parallel_write(word16 io_address, byte val)
|
||||
{
|
||||
//Mask MSB if user has it set.
|
||||
if(g_parallel_out_masking) {
|
||||
val = val & 0x7f;
|
||||
}
|
||||
//printf("parallel card called at %x\n", io_address);
|
||||
//send a byte to the virtual printer
|
||||
//By default all output to $C090 gets sent to the printer
|
||||
if (io_address == 0x00)
|
||||
{
|
||||
port_block = 1;
|
||||
printer_loop(val);
|
||||
printer_vbl_count = g_vbl_count+(g_printer_timeout*60);
|
||||
port_block = 0;
|
||||
}
|
||||
return;
|
||||
|
||||
void parallel_write(word16 io_address, byte val) {
|
||||
//Mask MSB if user has it set.
|
||||
if(g_parallel_out_masking) {
|
||||
val = val & 0x7f;
|
||||
}
|
||||
//printf("parallel card called at %x\n", io_address);
|
||||
//send a byte to the virtual printer
|
||||
//By default all output to $C090 gets sent to the printer
|
||||
if (io_address == 0x00)
|
||||
{
|
||||
port_block = 1;
|
||||
printer_loop(val);
|
||||
printer_vbl_count = g_vbl_count+(g_printer_timeout*60);
|
||||
port_block = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//This function handles the automatic timeout of the virtual printer if an
|
||||
//application doesn't send a form feed at the end of the page. It also
|
||||
//allows multipage mode Postscript and native printer documents to
|
||||
//print somewhat how a regular application would.
|
||||
void printer_update()
|
||||
{
|
||||
if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count)
|
||||
{
|
||||
printf("Calling printer_update and flushing!\n");
|
||||
printer_feed();
|
||||
printer_vbl_count = 0;
|
||||
}
|
||||
return;
|
||||
void printer_update() {
|
||||
if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count)
|
||||
{
|
||||
printf("Calling printer_update and flushing!\n");
|
||||
printer_feed();
|
||||
printer_vbl_count = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
228
src/partls.c
228
src/partls.c
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include <fcntl.h>
|
||||
|
@ -11,131 +11,127 @@
|
|||
#include <errno.h>
|
||||
|
||||
|
||||
#define BUF_SIZE 65536
|
||||
char buf[BUF_SIZE];
|
||||
#define BUF_SIZE 65536
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
void
|
||||
read_block(int fd, char *buf, int blk, int blk_size)
|
||||
{
|
||||
int ret;
|
||||
void read_block(int fd, char *buf, int blk, int blk_size) {
|
||||
int ret;
|
||||
|
||||
ret = lseek(fd, blk * blk_size, SEEK_SET);
|
||||
if(ret != blk * blk_size) {
|
||||
printf("lseek: %d, errno: %d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = lseek(fd, blk * blk_size, SEEK_SET);
|
||||
if(ret != blk * blk_size) {
|
||||
printf("lseek: %d, errno: %d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read(fd, buf, blk_size);
|
||||
if(ret != blk_size) {
|
||||
printf("ret: %d, errno: %d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = read(fd, buf, blk_size);
|
||||
if(ret != blk_size) {
|
||||
printf("ret: %d, errno: %d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Driver_desc *driver_desc_ptr;
|
||||
Part_map *part_map_ptr;
|
||||
double dsize;
|
||||
int fd;
|
||||
int block_size;
|
||||
word32 sig;
|
||||
word32 map_blk_cnt;
|
||||
word32 phys_part_start;
|
||||
word32 part_blk_cnt;
|
||||
word32 data_start;
|
||||
word32 data_cnt;
|
||||
int map_blocks;
|
||||
int cur;
|
||||
int long_form;
|
||||
int last_arg;
|
||||
int i;
|
||||
int main(int argc, char **argv) {
|
||||
Driver_desc *driver_desc_ptr;
|
||||
Part_map *part_map_ptr;
|
||||
double dsize;
|
||||
int fd;
|
||||
int block_size;
|
||||
word32 sig;
|
||||
word32 map_blk_cnt;
|
||||
word32 phys_part_start;
|
||||
word32 part_blk_cnt;
|
||||
word32 data_start;
|
||||
word32 data_cnt;
|
||||
int map_blocks;
|
||||
int cur;
|
||||
int long_form;
|
||||
int last_arg;
|
||||
int i;
|
||||
|
||||
/* parse args */
|
||||
long_form = 0;
|
||||
last_arg = 1;
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(!strcmp("-l", argv[i])) {
|
||||
long_form = 1;
|
||||
} else {
|
||||
last_arg = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* parse args */
|
||||
long_form = 0;
|
||||
last_arg = 1;
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(!strcmp("-l", argv[i])) {
|
||||
long_form = 1;
|
||||
} else {
|
||||
last_arg = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fd = open(argv[last_arg], O_RDONLY | O_BINARY, 0x1b6);
|
||||
if(fd < 0) {
|
||||
printf("open %s, ret: %d, errno:%d\n", argv[last_arg],fd,errno);
|
||||
exit(1);
|
||||
}
|
||||
if(long_form) {
|
||||
printf("fd: %d\n", fd);
|
||||
}
|
||||
fd = open(argv[last_arg], O_RDONLY | O_BINARY, 0x1b6);
|
||||
if(fd < 0) {
|
||||
printf("open %s, ret: %d, errno:%d\n", argv[last_arg],fd,errno);
|
||||
exit(1);
|
||||
}
|
||||
if(long_form) {
|
||||
printf("fd: %d\n", fd);
|
||||
}
|
||||
|
||||
block_size = 512;
|
||||
read_block(fd, buf, 0, block_size);
|
||||
block_size = 512;
|
||||
read_block(fd, buf, 0, block_size);
|
||||
|
||||
driver_desc_ptr = (Driver_desc *)buf;
|
||||
sig = GET_BE_WORD16(driver_desc_ptr->sig);
|
||||
block_size = GET_BE_WORD16(driver_desc_ptr->blk_size);
|
||||
if(long_form) {
|
||||
printf("sig: %04x, blksize: %04x\n", sig, block_size);
|
||||
}
|
||||
if(block_size == 0) {
|
||||
block_size = 512;
|
||||
}
|
||||
driver_desc_ptr = (Driver_desc *)buf;
|
||||
sig = GET_BE_WORD16(driver_desc_ptr->sig);
|
||||
block_size = GET_BE_WORD16(driver_desc_ptr->blk_size);
|
||||
if(long_form) {
|
||||
printf("sig: %04x, blksize: %04x\n", sig, block_size);
|
||||
}
|
||||
if(block_size == 0) {
|
||||
block_size = 512;
|
||||
}
|
||||
|
||||
if(sig == 0x4552 && block_size >= 0x200) {
|
||||
if(long_form) {
|
||||
printf("good!\n");
|
||||
}
|
||||
} else {
|
||||
printf("bad sig:%04x or block_size:%04x!\n", sig, block_size);
|
||||
exit(1);
|
||||
}
|
||||
if(sig == 0x4552 && block_size >= 0x200) {
|
||||
if(long_form) {
|
||||
printf("good!\n");
|
||||
}
|
||||
} else {
|
||||
printf("bad sig:%04x or block_size:%04x!\n", sig, block_size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
map_blocks = 1;
|
||||
cur = 0;
|
||||
while(cur < map_blocks) {
|
||||
read_block(fd, buf, cur + 1, block_size);
|
||||
part_map_ptr = (Part_map *)buf;
|
||||
sig = GET_BE_WORD16(part_map_ptr->sig);
|
||||
map_blk_cnt = GET_BE_WORD32(part_map_ptr->map_blk_cnt);
|
||||
phys_part_start = GET_BE_WORD32(part_map_ptr->phys_part_start);
|
||||
part_blk_cnt = GET_BE_WORD32(part_map_ptr->part_blk_cnt);
|
||||
data_start = GET_BE_WORD32(part_map_ptr->data_start);
|
||||
data_cnt = GET_BE_WORD32(part_map_ptr->data_cnt);
|
||||
map_blocks = 1;
|
||||
cur = 0;
|
||||
while(cur < map_blocks) {
|
||||
read_block(fd, buf, cur + 1, block_size);
|
||||
part_map_ptr = (Part_map *)buf;
|
||||
sig = GET_BE_WORD16(part_map_ptr->sig);
|
||||
map_blk_cnt = GET_BE_WORD32(part_map_ptr->map_blk_cnt);
|
||||
phys_part_start = GET_BE_WORD32(part_map_ptr->phys_part_start);
|
||||
part_blk_cnt = GET_BE_WORD32(part_map_ptr->part_blk_cnt);
|
||||
data_start = GET_BE_WORD32(part_map_ptr->data_start);
|
||||
data_cnt = GET_BE_WORD32(part_map_ptr->data_cnt);
|
||||
|
||||
if(cur == 0) {
|
||||
map_blocks = MIN(100, map_blk_cnt);
|
||||
}
|
||||
if(cur == 0) {
|
||||
map_blocks = MIN(100, map_blk_cnt);
|
||||
}
|
||||
|
||||
if(long_form) {
|
||||
printf("%2d: sig: %04x, map_blk_cnt: %d, "
|
||||
"phys_part_start: %08x, part_blk_cnt: %08x\n",
|
||||
cur, sig, map_blk_cnt, phys_part_start,
|
||||
part_blk_cnt);
|
||||
printf(" part_name: %s, part_type: %s\n",
|
||||
part_map_ptr->part_name,
|
||||
part_map_ptr->part_type);
|
||||
printf(" data_start:%08x, data_cnt:%08x status:%08x\n",
|
||||
GET_BE_WORD32(part_map_ptr->data_start),
|
||||
GET_BE_WORD32(part_map_ptr->data_cnt),
|
||||
GET_BE_WORD32(part_map_ptr->part_status));
|
||||
printf(" processor: %s\n", part_map_ptr->processor);
|
||||
} else {
|
||||
dsize = (double)GET_BE_WORD32(part_map_ptr->data_cnt);
|
||||
printf("%2d:%-20s size=%6.2fMB type=%s\n", cur,
|
||||
part_map_ptr->part_name,
|
||||
(dsize/(1024.0*2.0)),
|
||||
part_map_ptr->part_type);
|
||||
}
|
||||
if(long_form) {
|
||||
printf("%2d: sig: %04x, map_blk_cnt: %d, "
|
||||
"phys_part_start: %08x, part_blk_cnt: %08x\n",
|
||||
cur, sig, map_blk_cnt, phys_part_start,
|
||||
part_blk_cnt);
|
||||
printf(" part_name: %s, part_type: %s\n",
|
||||
part_map_ptr->part_name,
|
||||
part_map_ptr->part_type);
|
||||
printf(" data_start:%08x, data_cnt:%08x status:%08x\n",
|
||||
GET_BE_WORD32(part_map_ptr->data_start),
|
||||
GET_BE_WORD32(part_map_ptr->data_cnt),
|
||||
GET_BE_WORD32(part_map_ptr->part_status));
|
||||
printf(" processor: %s\n", part_map_ptr->processor);
|
||||
} else {
|
||||
dsize = (double)GET_BE_WORD32(part_map_ptr->data_cnt);
|
||||
printf("%2d:%-20s size=%6.2fMB type=%s\n", cur,
|
||||
part_map_ptr->part_name,
|
||||
(dsize/(1024.0*2.0)),
|
||||
part_map_ptr->part_type);
|
||||
}
|
||||
|
||||
cur++;
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,23 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Copyright (C) 2010 - 2011 by GSport contributors
|
||||
|
||||
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
|
||||
|
||||
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
|
||||
option) any later version.
|
||||
|
||||
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
|
||||
for more details.
|
||||
|
||||
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.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/* This is an interface between the SCC emulation and the Virtual Imagewriter. */
|
||||
|
||||
|
@ -25,122 +25,118 @@ word32 imagewriter_vbl_count = 0;
|
|||
int imagewriter_port_block = 0;
|
||||
int iw_scc_write = 0;
|
||||
|
||||
int scc_imagewriter_init(int port)
|
||||
{
|
||||
Scc *scc_ptr;
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
imagewriter_init(g_imagewriter_dpi,g_imagewriter_paper,g_imagewriter_banner,g_imagewriter_output,g_imagewriter_multipage);
|
||||
scc_ptr->state = 4;
|
||||
return 4;
|
||||
int scc_imagewriter_init(int port) {
|
||||
Scc *scc_ptr;
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
imagewriter_init(g_imagewriter_dpi,g_imagewriter_paper,g_imagewriter_banner,g_imagewriter_output,g_imagewriter_multipage);
|
||||
scc_ptr->state = 4;
|
||||
return 4;
|
||||
}
|
||||
|
||||
/** Transfer data from Imagewriter to the SCC **/
|
||||
void scc_imagewriter_fill_readbuf(int port, int space_left, double dcycs)
|
||||
{
|
||||
if (iw_scc_write)
|
||||
{
|
||||
size_t bytes_read;
|
||||
size_t i;
|
||||
byte data[9];
|
||||
if (g_imagewriter == 1)
|
||||
{
|
||||
//Imagewriter LQ self ID string. Tell machine we have a color ribbon and sheet feeder installed.
|
||||
data[0] = 0; //Start bit
|
||||
data[1] ='L'; //Printer type is Imagewriter LQ
|
||||
data[2] ='Q'; //(cont)
|
||||
data[3] ='1'; //15 inch carriage width
|
||||
data[4] ='C'; //Color ribbon installed
|
||||
data[5] ='F'; //Sheet feeder installed, no envelope attachment
|
||||
data[6] ='1'; //Number of sheet feeder bins
|
||||
data[7] = 0x0D; //CR terminates string
|
||||
data[8] = 0; //Stop bit
|
||||
bytes_read = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Imagewriter II self ID string. Tell machine we have a color ribbon and sheet feeder installed.
|
||||
data[0] = 0; //Start bit
|
||||
data[1] ='I'; //Printer type is Imagewriter II
|
||||
data[2] ='W'; //(cont)
|
||||
data[3] ='1'; //10 inch carriage width
|
||||
data[4] ='0'; //(cont)
|
||||
data[5] ='C'; //Color ribbon installed
|
||||
data[6] ='F'; //Sheet feeder installed
|
||||
data[7] = 0; //Stop bit
|
||||
bytes_read = 8;
|
||||
}
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, data[i], dcycs);
|
||||
}
|
||||
iw_scc_write = 0;
|
||||
}
|
||||
void scc_imagewriter_fill_readbuf(int port, int space_left, double dcycs) {
|
||||
if (iw_scc_write)
|
||||
{
|
||||
size_t bytes_read;
|
||||
size_t i;
|
||||
byte data[9];
|
||||
if (g_imagewriter == 1)
|
||||
{
|
||||
//Imagewriter LQ self ID string. Tell machine we have a color ribbon and sheet feeder installed.
|
||||
data[0] = 0; //Start bit
|
||||
data[1] ='L'; //Printer type is Imagewriter LQ
|
||||
data[2] ='Q'; //(cont)
|
||||
data[3] ='1'; //15 inch carriage width
|
||||
data[4] ='C'; //Color ribbon installed
|
||||
data[5] ='F'; //Sheet feeder installed, no envelope attachment
|
||||
data[6] ='1'; //Number of sheet feeder bins
|
||||
data[7] = 0x0D; //CR terminates string
|
||||
data[8] = 0; //Stop bit
|
||||
bytes_read = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Imagewriter II self ID string. Tell machine we have a color ribbon and sheet feeder installed.
|
||||
data[0] = 0; //Start bit
|
||||
data[1] ='I'; //Printer type is Imagewriter II
|
||||
data[2] ='W'; //(cont)
|
||||
data[3] ='1'; //10 inch carriage width
|
||||
data[4] ='0'; //(cont)
|
||||
data[5] ='C'; //Color ribbon installed
|
||||
data[6] ='F'; //Sheet feeder installed
|
||||
data[7] = 0; //Stop bit
|
||||
bytes_read = 8;
|
||||
}
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, data[i], dcycs);
|
||||
}
|
||||
iw_scc_write = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Transfer data from the SCC to the Imagewriter. **/
|
||||
void scc_imagewriter_empty_writebuf(int port, double dcycs)
|
||||
{
|
||||
Scc* scc_ptr;
|
||||
void scc_imagewriter_empty_writebuf(int port, double dcycs) {
|
||||
Scc* scc_ptr;
|
||||
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int len;
|
||||
int done;
|
||||
//int ret;
|
||||
unsigned long bytes_written;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int len;
|
||||
int done;
|
||||
//int ret;
|
||||
unsigned long bytes_written;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
bytes_written = 1;
|
||||
imagewriter_port_block = 1;
|
||||
imagewriter_loop(scc_ptr->out_buf[rdptr]);
|
||||
imagewriter_vbl_count = g_vbl_count+(g_imagewriter_timeout*60);
|
||||
imagewriter_port_block = 0;
|
||||
//printf("Write Imagewriter ret: %d, bytes_written:%d, len:%d\n", ret,
|
||||
//(int)bytes_written, len);
|
||||
|
||||
if (bytes_written == 0) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + bytes_written;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
bytes_written = 1;
|
||||
imagewriter_port_block = 1;
|
||||
imagewriter_loop(scc_ptr->out_buf[rdptr]);
|
||||
imagewriter_vbl_count = g_vbl_count+(g_imagewriter_timeout*60);
|
||||
imagewriter_port_block = 0;
|
||||
//printf("Write Imagewriter ret: %d, bytes_written:%d, len:%d\n", ret,
|
||||
//(int)bytes_written, len);
|
||||
|
||||
if (bytes_written == 0) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + bytes_written;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This function handles the automatic timeout of the virtual printer if an
|
||||
//application doesn't send a form feed at the end of the page. It also
|
||||
//allows multipage mode Postscript and native printer documents to
|
||||
//print somewhat how a regular application would.
|
||||
void imagewriter_update()
|
||||
{
|
||||
if (imagewriter_port_block != 1 && imagewriter_vbl_count != 0 && g_vbl_count >= imagewriter_vbl_count)
|
||||
{
|
||||
printf("Calling imagewriter_update and flushing!\n");
|
||||
imagewriter_feed();
|
||||
imagewriter_vbl_count = 0;
|
||||
}
|
||||
return;
|
||||
void imagewriter_update() {
|
||||
if (imagewriter_port_block != 1 && imagewriter_vbl_count != 0 && g_vbl_count >= imagewriter_vbl_count)
|
||||
{
|
||||
printf("Calling imagewriter_update and flushing!\n");
|
||||
imagewriter_feed();
|
||||
imagewriter_vbl_count = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
174
src/scc_llap.c
174
src/scc_llap.c
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/* This is an interface between the SCC emulation and the LAP bridge. */
|
||||
|
||||
|
@ -25,128 +25,118 @@ extern Scc scc_stat[2];
|
|||
extern int g_config_gsplus_update_needed;
|
||||
static bool bridge_initialized = false;
|
||||
|
||||
void scc_llap_init()
|
||||
{
|
||||
atbridge_set_diagnostics(g_appletalk_diagnostics);
|
||||
bridge_initialized = atbridge_init();
|
||||
atbridge_set_net(g_appletalk_network_hint);
|
||||
void scc_llap_init() {
|
||||
atbridge_set_diagnostics(g_appletalk_diagnostics);
|
||||
bridge_initialized = atbridge_init();
|
||||
atbridge_set_net(g_appletalk_network_hint);
|
||||
}
|
||||
|
||||
void scc_llap_set_node(byte val)
|
||||
{
|
||||
atbridge_set_node(val);
|
||||
void scc_llap_set_node(byte val) {
|
||||
atbridge_set_node(val);
|
||||
}
|
||||
|
||||
void scc_llap_update()
|
||||
{
|
||||
if (bridge_initialized)
|
||||
{
|
||||
atbridge_process();
|
||||
void scc_llap_update() {
|
||||
if (bridge_initialized)
|
||||
{
|
||||
atbridge_process();
|
||||
|
||||
// Save the AppleTalk network number. Since the network number does not
|
||||
// change very often, this will slightly improve startup time.
|
||||
if (g_appletalk_network_hint != atbridge_get_net())
|
||||
{
|
||||
g_appletalk_network_hint = atbridge_get_net();
|
||||
g_config_gsplus_update_needed = 1;
|
||||
}
|
||||
}
|
||||
// Save the AppleTalk network number. Since the network number does not
|
||||
// change very often, this will slightly improve startup time.
|
||||
if (g_appletalk_network_hint != atbridge_get_net())
|
||||
{
|
||||
g_appletalk_network_hint = atbridge_get_net();
|
||||
g_config_gsplus_update_needed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Transfer one packet from the bridge to the SCC **/
|
||||
void scc_llap_fill_readbuf(int port, int space_left, double dcycs)
|
||||
{
|
||||
atbridge_set_diagnostics(g_appletalk_diagnostics);
|
||||
void scc_llap_fill_readbuf(int port, int space_left, double dcycs) {
|
||||
atbridge_set_diagnostics(g_appletalk_diagnostics);
|
||||
|
||||
byte* data;
|
||||
byte* data;
|
||||
|
||||
if (!bridge_initialized)
|
||||
return;
|
||||
if (!bridge_initialized)
|
||||
return;
|
||||
|
||||
data = NULL;
|
||||
size_t bytes_read;
|
||||
size_t i;
|
||||
data = NULL;
|
||||
size_t bytes_read;
|
||||
size_t i;
|
||||
|
||||
llap_dequeue_out(dcycs, &bytes_read, &data);
|
||||
llap_dequeue_out(dcycs, &bytes_read, &data);
|
||||
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, data[i], dcycs);
|
||||
}
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, data[i], dcycs);
|
||||
}
|
||||
|
||||
free(data);
|
||||
free(data);
|
||||
|
||||
// Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
|
||||
scc_llap_update();
|
||||
// Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
|
||||
scc_llap_update();
|
||||
}
|
||||
|
||||
/** Transfer one packet from the SCC to the AppleTalk bridge. **/
|
||||
void scc_llap_empty_writebuf(int port, double dcycs)
|
||||
{
|
||||
atbridge_set_diagnostics(g_appletalk_diagnostics);
|
||||
void scc_llap_empty_writebuf(int port, double dcycs) {
|
||||
atbridge_set_diagnostics(g_appletalk_diagnostics);
|
||||
|
||||
Scc* scc_ptr;
|
||||
Scc* scc_ptr;
|
||||
|
||||
if (!bridge_initialized)
|
||||
return;
|
||||
if (!bridge_initialized)
|
||||
return;
|
||||
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int len;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int len;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
// If there's data in the output buffer, send it.
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr)
|
||||
return;
|
||||
|
||||
len = wrptr - rdptr;
|
||||
if (len < 0)
|
||||
{
|
||||
// The data is not contiguous since it wraps around the end of the buffer.
|
||||
// But, this should never happen since this function always empties the entire
|
||||
// buffer, and the buffer is large enough to hold the maximum packet size.
|
||||
halt_printf("SCC LLAP: Unexpected non-contiguous data. Dropping packet.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The data is contiguous, so read the data directly from the buffer.
|
||||
llap_enqueue_in(dcycs, len, &scc_ptr->out_buf[rdptr]);
|
||||
}
|
||||
|
||||
// Remove the sent data from the output buffer. Since the buffer contains
|
||||
// one complete packet, always send all of the data.
|
||||
scc_ptr->out_rdptr = 0;
|
||||
scc_ptr->out_wrptr = 0;
|
||||
// If there's data in the output buffer, send it.
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr)
|
||||
return;
|
||||
|
||||
// Latch EOM to indicate that the SCC has sent the message.
|
||||
// The timing will be a bit off from the real hardware since we're not
|
||||
// emulating the sending hardware timing and CRC generation.
|
||||
scc_ptr->eom = 1;
|
||||
len = wrptr - rdptr;
|
||||
if (len < 0)
|
||||
{
|
||||
// The data is not contiguous since it wraps around the end of the buffer.
|
||||
// But, this should never happen since this function always empties the entire
|
||||
// buffer, and the buffer is large enough to hold the maximum packet size.
|
||||
halt_printf("SCC LLAP: Unexpected non-contiguous data. Dropping packet.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The data is contiguous, so read the data directly from the buffer.
|
||||
llap_enqueue_in(dcycs, len, &scc_ptr->out_buf[rdptr]);
|
||||
}
|
||||
|
||||
// Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
|
||||
scc_llap_update();
|
||||
// Remove the sent data from the output buffer. Since the buffer contains
|
||||
// one complete packet, always send all of the data.
|
||||
scc_ptr->out_rdptr = 0;
|
||||
scc_ptr->out_wrptr = 0;
|
||||
|
||||
// Latch EOM to indicate that the SCC has sent the message.
|
||||
// The timing will be a bit off from the real hardware since we're not
|
||||
// emulating the sending hardware timing and CRC generation.
|
||||
scc_ptr->eom = 1;
|
||||
|
||||
// Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
|
||||
scc_llap_update();
|
||||
}
|
||||
|
||||
#else
|
||||
void scc_llap_init()
|
||||
{
|
||||
void scc_llap_init() {
|
||||
}
|
||||
|
||||
void scc_llap_set_node(byte val)
|
||||
{
|
||||
void scc_llap_set_node(byte val) {
|
||||
}
|
||||
|
||||
void scc_llap_update()
|
||||
{
|
||||
void scc_llap_update() {
|
||||
}
|
||||
|
||||
void scc_llap_fill_readbuf(int port, int space_left, double dcycs)
|
||||
{
|
||||
void scc_llap_fill_readbuf(int port, int space_left, double dcycs) {
|
||||
}
|
||||
|
||||
void scc_llap_empty_writebuf(int port, double dcycs)
|
||||
{
|
||||
void scc_llap_empty_writebuf(int port, double dcycs) {
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/* This file contains the Mac serial calls */
|
||||
|
||||
|
@ -18,191 +18,183 @@ extern Scc scc_stat[2];
|
|||
extern word32 g_c025_val;
|
||||
|
||||
#ifdef MAC
|
||||
int
|
||||
scc_serial_mac_init(int port)
|
||||
{
|
||||
char str_buf[1024];
|
||||
Scc *scc_ptr;
|
||||
int state;
|
||||
int fd;
|
||||
int scc_serial_mac_init(int port) {
|
||||
char str_buf[1024];
|
||||
Scc *scc_ptr;
|
||||
int state;
|
||||
int fd;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
scc_ptr->state = 0; /* mark as uninitialized */
|
||||
scc_ptr->state = 0; /* mark as uninitialized */
|
||||
|
||||
/*sprintf(&str_buf[0], "/dev/tty.USA19QW11P1.1"); */
|
||||
sprintf(&str_buf[0], "/dev/tty.USA19H181P1.1");
|
||||
/* HACK: fix this... */
|
||||
/*sprintf(&str_buf[0], "/dev/tty.USA19QW11P1.1"); */
|
||||
sprintf(&str_buf[0], "/dev/tty.USA19H181P1.1");
|
||||
/* HACK: fix this... */
|
||||
|
||||
fd = open(&str_buf[0], O_RDWR | O_NONBLOCK);
|
||||
fd = open(&str_buf[0], O_RDWR | O_NONBLOCK);
|
||||
|
||||
scc_ptr->host_handle = (void *)fd;
|
||||
scc_ptr->host_handle2 = 0;
|
||||
scc_ptr->host_handle = (void *)fd;
|
||||
scc_ptr->host_handle2 = 0;
|
||||
|
||||
printf("scc_serial_mac_init %d called, fd: %d\n", port, fd);
|
||||
printf("scc_serial_mac_init %d called, fd: %d\n", port, fd);
|
||||
|
||||
if(fd < 0) {
|
||||
scc_ptr->host_handle = (void *)-1;
|
||||
return -1;
|
||||
}
|
||||
if(fd < 0) {
|
||||
scc_ptr->host_handle = (void *)-1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
scc_serial_mac_change_params(port);
|
||||
scc_serial_mac_change_params(port);
|
||||
|
||||
state = 2; /* raw serial */
|
||||
scc_ptr->state = state;
|
||||
state = 2; /* raw serial */
|
||||
scc_ptr->state = state;
|
||||
|
||||
return state;
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_mac_change_params(int port)
|
||||
{
|
||||
struct termios termios_buf;
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int csz;
|
||||
int ret;
|
||||
void scc_serial_mac_change_params(int port) {
|
||||
struct termios termios_buf;
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int csz;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
fd = (intptr_t)scc_ptr->host_handle;
|
||||
printf("scc_serial_mac_change_parms port: %d, fd: %d\n", port, fd);
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
fd = (intptr_t)scc_ptr->host_handle;
|
||||
printf("scc_serial_mac_change_parms port: %d, fd: %d\n", port, fd);
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = tcgetattr(fd, &termios_buf);
|
||||
if(ret != 0) {
|
||||
printf("tcgetattr port%d ret: %d\n", port, ret);
|
||||
}
|
||||
ret = tcgetattr(fd, &termios_buf);
|
||||
if(ret != 0) {
|
||||
printf("tcgetattr port%d ret: %d\n", port, ret);
|
||||
}
|
||||
|
||||
#if 1
|
||||
printf("baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n",
|
||||
(int)termios_buf.c_ispeed, (int)termios_buf.c_iflag,
|
||||
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
|
||||
(int)termios_buf.c_lflag);
|
||||
printf("baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n",
|
||||
(int)termios_buf.c_ispeed, (int)termios_buf.c_iflag,
|
||||
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
|
||||
(int)termios_buf.c_lflag);
|
||||
#endif
|
||||
|
||||
memset(&termios_buf, 0, sizeof(struct termios));
|
||||
cfmakeraw(&termios_buf);
|
||||
cfsetspeed(&termios_buf, scc_ptr->baud_rate);
|
||||
memset(&termios_buf, 0, sizeof(struct termios));
|
||||
cfmakeraw(&termios_buf);
|
||||
cfsetspeed(&termios_buf, scc_ptr->baud_rate);
|
||||
|
||||
csz = scc_ptr->char_size;
|
||||
termios_buf.c_cflag = CREAD | CLOCAL;
|
||||
termios_buf.c_cflag |= (csz == 5) ? CS5 :
|
||||
(csz == 6) ? CS6 :
|
||||
(csz == 7) ? CS7 :
|
||||
CS8;
|
||||
switch((scc_ptr->reg[4] >> 2) & 0x3) {
|
||||
case 2: // 1.5 stop bits
|
||||
termios_buf.c_cflag |= CSTOPB; /* no 1.5 stop bit setting.*/
|
||||
break;
|
||||
case 3: // 2 stop bits
|
||||
termios_buf.c_cflag |= CSTOPB;
|
||||
break;
|
||||
}
|
||||
csz = scc_ptr->char_size;
|
||||
termios_buf.c_cflag = CREAD | CLOCAL;
|
||||
termios_buf.c_cflag |= (csz == 5) ? CS5 :
|
||||
(csz == 6) ? CS6 :
|
||||
(csz == 7) ? CS7 :
|
||||
CS8;
|
||||
switch((scc_ptr->reg[4] >> 2) & 0x3) {
|
||||
case 2: // 1.5 stop bits
|
||||
termios_buf.c_cflag |= CSTOPB; /* no 1.5 stop bit setting.*/
|
||||
break;
|
||||
case 3: // 2 stop bits
|
||||
termios_buf.c_cflag |= CSTOPB;
|
||||
break;
|
||||
}
|
||||
|
||||
switch((scc_ptr->reg[4]) & 0x3) {
|
||||
case 1: // Odd parity
|
||||
termios_buf.c_cflag |= (PARENB | PARODD);
|
||||
break;
|
||||
case 3: // Even parity
|
||||
termios_buf.c_cflag |= PARENB;
|
||||
break;
|
||||
}
|
||||
switch((scc_ptr->reg[4]) & 0x3) {
|
||||
case 1: // Odd parity
|
||||
termios_buf.c_cflag |= (PARENB | PARODD);
|
||||
break;
|
||||
case 3: // Even parity
|
||||
termios_buf.c_cflag |= PARENB;
|
||||
break;
|
||||
}
|
||||
|
||||
/* always enabled DTR and RTS control */
|
||||
termios_buf.c_cflag |= CDTR_IFLOW | CRTS_IFLOW;
|
||||
/* always enabled DTR and RTS control */
|
||||
termios_buf.c_cflag |= CDTR_IFLOW | CRTS_IFLOW;
|
||||
|
||||
printf("fd: %d, baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n",
|
||||
fd, (int)termios_buf.c_ispeed, (int)termios_buf.c_iflag,
|
||||
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
|
||||
(int)termios_buf.c_lflag);
|
||||
ret = tcsetattr(fd, TCSANOW, &termios_buf);
|
||||
if(ret != 0) {
|
||||
printf("tcsetattr ret: %d\n", ret);
|
||||
}
|
||||
printf("fd: %d, baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n",
|
||||
fd, (int)termios_buf.c_ispeed, (int)termios_buf.c_iflag,
|
||||
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
|
||||
(int)termios_buf.c_lflag);
|
||||
ret = tcsetattr(fd, TCSANOW, &termios_buf);
|
||||
if(ret != 0) {
|
||||
printf("tcsetattr ret: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs)
|
||||
{
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int i;
|
||||
int ret;
|
||||
void scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs) {
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
fd = (intptr_t)scc_ptr->host_handle;
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
fd = (intptr_t)scc_ptr->host_handle;
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try reading some bytes */
|
||||
space_left = MIN(space_left, 256);
|
||||
ret = read(fd, tmp_buf, space_left);
|
||||
/* Try reading some bytes */
|
||||
space_left = MIN(space_left, 256);
|
||||
ret = read(fd, tmp_buf, space_left);
|
||||
|
||||
if(ret > 0) {
|
||||
for(i = 0; i < ret; i++) {
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret > 0) {
|
||||
for(i = 0; i < ret; i++) {
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_mac_empty_writebuf(int port)
|
||||
{
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int done;
|
||||
int ret;
|
||||
int len;
|
||||
void scc_serial_mac_empty_writebuf(int port) {
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int done;
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
fd = (intptr_t)scc_ptr->host_handle;
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
fd = (intptr_t)scc_ptr->host_handle;
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
ret = write(fd, &(scc_ptr->out_buf[rdptr]), len);
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
ret = write(fd, &(scc_ptr->out_buf[rdptr]), len);
|
||||
|
||||
if(ret <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + ret;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
if(ret <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + ret;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MAC */
|
||||
#endif /* MAC */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
/* This file contains the Win32 COM1/COM2 calls */
|
||||
|
||||
|
@ -23,238 +23,230 @@ extern Scc scc_stat[2];
|
|||
extern word32 g_c025_val;
|
||||
|
||||
#ifdef _WIN32
|
||||
int
|
||||
scc_serial_win_init(int port)
|
||||
{
|
||||
COMMTIMEOUTS commtimeouts;
|
||||
TCHAR str_buf[8];
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
int state;
|
||||
int ret;
|
||||
int scc_serial_win_init(int port) {
|
||||
COMMTIMEOUTS commtimeouts;
|
||||
TCHAR str_buf[8];
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
int state;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
scc_ptr->state = 0; /* mark as failed */
|
||||
scc_ptr->state = 0; /* mark as failed */
|
||||
|
||||
#ifdef UNICODE
|
||||
wsprintf(&str_buf[0], _T("COM%d"), port+1);
|
||||
wsprintf(&str_buf[0], _T("COM%d"), port+1);
|
||||
#else
|
||||
sprintf(&str_buf[0], "COM%d", port+1);
|
||||
sprintf(&str_buf[0], "COM%d", port+1);
|
||||
#endif
|
||||
host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
scc_ptr->host_handle = host_handle;
|
||||
scc_ptr->host_handle2 = malloc(sizeof(DCB));
|
||||
scc_ptr->host_handle = host_handle;
|
||||
scc_ptr->host_handle2 = malloc(sizeof(DCB));
|
||||
|
||||
printf("scc_socket_init %d called, host_handle: %p\n", port,
|
||||
host_handle);
|
||||
printf("scc_socket_init %d called, host_handle: %p\n", port,
|
||||
host_handle);
|
||||
|
||||
if(host_handle == INVALID_HANDLE_VALUE) {
|
||||
scc_ptr->host_handle = 0;
|
||||
return 0;
|
||||
}
|
||||
if(host_handle == INVALID_HANDLE_VALUE) {
|
||||
scc_ptr->host_handle = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
scc_serial_win_change_params(port);
|
||||
scc_serial_win_change_params(port);
|
||||
|
||||
|
||||
commtimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
commtimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
commtimeouts.ReadTotalTimeoutConstant = 0;
|
||||
commtimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
commtimeouts.WriteTotalTimeoutConstant = 10;
|
||||
ret = SetCommTimeouts(host_handle, &commtimeouts);
|
||||
if(ret == 0) {
|
||||
printf("setcommtimeout ret: %d\n", ret);
|
||||
}
|
||||
commtimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
commtimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
commtimeouts.ReadTotalTimeoutConstant = 0;
|
||||
commtimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
commtimeouts.WriteTotalTimeoutConstant = 10;
|
||||
ret = SetCommTimeouts(host_handle, &commtimeouts);
|
||||
if(ret == 0) {
|
||||
printf("setcommtimeout ret: %d\n", ret);
|
||||
}
|
||||
|
||||
state = 2; /* raw serial */
|
||||
scc_ptr->state = state;
|
||||
state = 2; /* raw serial */
|
||||
scc_ptr->state = state;
|
||||
|
||||
return state;
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_win_change_params(int port)
|
||||
{
|
||||
DCB *dcbptr;
|
||||
HANDLE host_handle;
|
||||
Scc *scc_ptr;
|
||||
int ret;
|
||||
void scc_serial_win_change_params(int port) {
|
||||
DCB *dcbptr;
|
||||
HANDLE host_handle;
|
||||
Scc *scc_ptr;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
host_handle = scc_ptr->host_handle;
|
||||
dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
host_handle = scc_ptr->host_handle;
|
||||
dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = GetCommState(host_handle, dcbptr);
|
||||
if(ret == 0) {
|
||||
printf("getcomm port%d ret: %d\n", port, ret);
|
||||
}
|
||||
ret = GetCommState(host_handle, dcbptr);
|
||||
if(ret == 0) {
|
||||
printf("getcomm port%d ret: %d\n", port, ret);
|
||||
}
|
||||
|
||||
#if 1
|
||||
printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n",
|
||||
(int)dcbptr->BaudRate, (int)dcbptr->ByteSize,
|
||||
(int)dcbptr->StopBits, (int)dcbptr->Parity);
|
||||
printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n",
|
||||
(int)dcbptr->fBinary,
|
||||
(int)dcbptr->fOutxCtsFlow,
|
||||
(int)dcbptr->fOutxDsrFlow,
|
||||
(int)dcbptr->fDtrControl,
|
||||
(int)dcbptr->fDsrSensitivity);
|
||||
printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n",
|
||||
(int)dcbptr->fTXContinueOnXoff,
|
||||
(int)dcbptr->fOutX,
|
||||
(int)dcbptr->fInX,
|
||||
(int)dcbptr->fNull,
|
||||
(int)dcbptr->fRtsControl);
|
||||
printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError,
|
||||
(int)dcbptr->fParity);
|
||||
printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n",
|
||||
(int)dcbptr->BaudRate, (int)dcbptr->ByteSize,
|
||||
(int)dcbptr->StopBits, (int)dcbptr->Parity);
|
||||
printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n",
|
||||
(int)dcbptr->fBinary,
|
||||
(int)dcbptr->fOutxCtsFlow,
|
||||
(int)dcbptr->fOutxDsrFlow,
|
||||
(int)dcbptr->fDtrControl,
|
||||
(int)dcbptr->fDsrSensitivity);
|
||||
printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n",
|
||||
(int)dcbptr->fTXContinueOnXoff,
|
||||
(int)dcbptr->fOutX,
|
||||
(int)dcbptr->fInX,
|
||||
(int)dcbptr->fNull,
|
||||
(int)dcbptr->fRtsControl);
|
||||
printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError,
|
||||
(int)dcbptr->fParity);
|
||||
#endif
|
||||
|
||||
dcbptr->fAbortOnError = 0;
|
||||
dcbptr->fAbortOnError = 0;
|
||||
|
||||
dcbptr->BaudRate = scc_ptr->baud_rate;
|
||||
dcbptr->ByteSize = scc_ptr->char_size;
|
||||
dcbptr->StopBits = ONESTOPBIT;
|
||||
switch((scc_ptr->reg[4] >> 2) & 0x3) {
|
||||
case 2: // 1.5 stop bits
|
||||
dcbptr->StopBits = ONE5STOPBITS;
|
||||
break;
|
||||
case 3: // 2 stop bits
|
||||
dcbptr->StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
}
|
||||
dcbptr->BaudRate = scc_ptr->baud_rate;
|
||||
dcbptr->ByteSize = scc_ptr->char_size;
|
||||
dcbptr->StopBits = ONESTOPBIT;
|
||||
switch((scc_ptr->reg[4] >> 2) & 0x3) {
|
||||
case 2: // 1.5 stop bits
|
||||
dcbptr->StopBits = ONE5STOPBITS;
|
||||
break;
|
||||
case 3: // 2 stop bits
|
||||
dcbptr->StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
}
|
||||
|
||||
dcbptr->Parity = NOPARITY;
|
||||
switch((scc_ptr->reg[4]) & 0x3) {
|
||||
case 1: // Odd parity
|
||||
dcbptr->Parity = ODDPARITY;
|
||||
break;
|
||||
case 3: // Even parity
|
||||
dcbptr->Parity = EVENPARITY;
|
||||
break;
|
||||
}
|
||||
dcbptr->Parity = NOPARITY;
|
||||
switch((scc_ptr->reg[4]) & 0x3) {
|
||||
case 1: // Odd parity
|
||||
dcbptr->Parity = ODDPARITY;
|
||||
break;
|
||||
case 3: // Even parity
|
||||
dcbptr->Parity = EVENPARITY;
|
||||
break;
|
||||
}
|
||||
|
||||
dcbptr->fNull = 0;
|
||||
dcbptr->fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcbptr->fDsrSensitivity = 0;
|
||||
dcbptr->fOutxCtsFlow = 0;
|
||||
dcbptr->fOutxDsrFlow = 0;
|
||||
dcbptr->fParity = 0;
|
||||
dcbptr->fInX = 0;
|
||||
dcbptr->fOutX = 0;
|
||||
dcbptr->fRtsControl = RTS_CONTROL_ENABLE;
|
||||
dcbptr->fNull = 0;
|
||||
dcbptr->fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcbptr->fDsrSensitivity = 0;
|
||||
dcbptr->fOutxCtsFlow = 0;
|
||||
dcbptr->fOutxDsrFlow = 0;
|
||||
dcbptr->fParity = 0;
|
||||
dcbptr->fInX = 0;
|
||||
dcbptr->fOutX = 0;
|
||||
dcbptr->fRtsControl = RTS_CONTROL_ENABLE;
|
||||
|
||||
ret = SetCommState(host_handle, dcbptr);
|
||||
if(ret == 0) {
|
||||
printf("SetCommState ret: %d, new baud: %d\n", ret,
|
||||
(int)dcbptr->BaudRate);
|
||||
}
|
||||
ret = SetCommState(host_handle, dcbptr);
|
||||
if(ret == 0) {
|
||||
printf("SetCommState ret: %d, new baud: %d\n", ret,
|
||||
(int)dcbptr->BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_win_fill_readbuf(int port, int space_left, double dcycs)
|
||||
{
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
DWORD bytes_read;
|
||||
DWORD i;
|
||||
int ret;
|
||||
void scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) {
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
DWORD bytes_read;
|
||||
DWORD i;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
host_handle = scc_ptr->host_handle;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
host_handle = scc_ptr->host_handle;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try reading some bytes */
|
||||
space_left = MIN(256, space_left);
|
||||
ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL);
|
||||
/* Try reading some bytes */
|
||||
space_left = MIN(256, space_left);
|
||||
ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL);
|
||||
|
||||
if(ret == 0) {
|
||||
printf("ReadFile ret 0\n");
|
||||
}
|
||||
if(ret == 0) {
|
||||
printf("ReadFile ret 0\n");
|
||||
}
|
||||
|
||||
if(ret && (bytes_read > 0)) {
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret && (bytes_read > 0)) {
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_win_empty_writebuf(int port)
|
||||
{
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int done;
|
||||
word32 err_code;
|
||||
DWORD bytes_written;
|
||||
int ret;
|
||||
int len;
|
||||
void scc_serial_win_empty_writebuf(int port) {
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int done;
|
||||
word32 err_code;
|
||||
DWORD bytes_written;
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
//printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle);
|
||||
host_handle = scc_ptr->host_handle;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
//printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle);
|
||||
host_handle = scc_ptr->host_handle;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
bytes_written = 1;
|
||||
ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len,
|
||||
&bytes_written, NULL);
|
||||
printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret,
|
||||
(int)bytes_written, len);
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
bytes_written = 1;
|
||||
ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len,
|
||||
&bytes_written, NULL);
|
||||
printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret,
|
||||
(int)bytes_written, len);
|
||||
|
||||
err_code = (word32)-1;
|
||||
if(ret == 0) {
|
||||
err_code = (word32)GetLastError();
|
||||
printf("WriteFile ret:0, err_code: %08x\n", err_code);
|
||||
}
|
||||
err_code = (word32)-1;
|
||||
if(ret == 0) {
|
||||
err_code = (word32)GetLastError();
|
||||
printf("WriteFile ret:0, err_code: %08x\n", err_code);
|
||||
}
|
||||
|
||||
if(ret == 0 || (bytes_written == 0)) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + bytes_written;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
if(ret == 0 || (bytes_written == 0)) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + bytes_written;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
// fps shiz
|
||||
unsigned int lastTime = 0, currentTime, frames;
|
||||
|
@ -25,16 +25,16 @@ unsigned int lastTime = 0, currentTime, frames;
|
|||
#endif
|
||||
|
||||
// BITMASKS
|
||||
#define ShiftMask 1
|
||||
#define ControlMask 4
|
||||
#define LockMask 2
|
||||
#define ShiftMask 1
|
||||
#define ControlMask 4
|
||||
#define LockMask 2
|
||||
|
||||
int g_use_shmem = 0;
|
||||
|
||||
int g_num_check_input_calls = 0;
|
||||
int g_check_input_flush_rate = 2;
|
||||
int g_win_status_debug = 0; // Current visibility of status lines.
|
||||
int g_win_status_debug_request = 0; // Desired visibility of status lines.
|
||||
int g_win_status_debug = 0; // Current visibility of status lines.
|
||||
int g_win_status_debug_request = 0; // Desired visibility of status lines.
|
||||
int g_screen_mdepth = 0;
|
||||
int kb_shift_control_state = 0;
|
||||
|
||||
|
@ -67,7 +67,7 @@ extern word32 g_full_refresh_needed;
|
|||
extern word32 g_palette_8to1624[256];
|
||||
extern word32 g_a2palette_8to1624[256];
|
||||
extern Kimage g_mainwin_kimage;
|
||||
extern const char g_gsplus_version_str[]; // version string for title bar
|
||||
extern const char g_gsplus_version_str[]; // version string for title bar
|
||||
|
||||
SDL_Window *window; // Declare a pointer
|
||||
SDL_Renderer *renderer;
|
||||
|
@ -76,124 +76,123 @@ SDL_Texture *overlay_texture; // This is used for scanline simulation. Could be
|
|||
Uint32 *overlay_pixels;
|
||||
|
||||
static char *g_clipboard = NULL; // clipboard variables
|
||||
static size_t g_clipboard_pos = 0;
|
||||
static size_t g_clipboard_pos = 0;
|
||||
|
||||
void dev_video_init_sdl();
|
||||
void handle_sdl_key_event(SDL_Event event);
|
||||
void check_input_events_sdl();
|
||||
int handle_sdl_mouse_motion_event(SDL_Event event);
|
||||
|
||||
int g_num_a2_keycodes = 0;
|
||||
int g_num_a2_keycodes = 0;
|
||||
int a2_key_to_sdlkeycode[][3] = {
|
||||
{ 0x35, SDLK_ESCAPE,0 },
|
||||
{ 0x7a, SDLK_F1, 0 },
|
||||
{ 0x78, SDLK_F2, 0 },
|
||||
{ 0x63, SDLK_F3, 0 },
|
||||
{ 0x76, SDLK_F4, 0 },
|
||||
{ 0x60, SDLK_F5, 0 },
|
||||
{ 0x61, SDLK_F6, 0 },
|
||||
{ 0x62, SDLK_F7, 0 },
|
||||
{ 0x64, SDLK_F8, 0 },
|
||||
{ 0x65, SDLK_F9, 0 },
|
||||
{ 0x6d, SDLK_F10, 0 },
|
||||
{ 0x67, SDLK_F11, 0 },
|
||||
{ 0x6f, SDLK_F12, 0 },
|
||||
{ 0x69, SDLK_F13, 0 },
|
||||
{ 0x6b, SDLK_F14, 0 },
|
||||
{ 0x71, SDLK_F15, 0 },
|
||||
{ 0x35, SDLK_ESCAPE,0 },
|
||||
{ 0x7a, SDLK_F1, 0 },
|
||||
{ 0x78, SDLK_F2, 0 },
|
||||
{ 0x63, SDLK_F3, 0 },
|
||||
{ 0x76, SDLK_F4, 0 },
|
||||
{ 0x60, SDLK_F5, 0 },
|
||||
{ 0x61, SDLK_F6, 0 },
|
||||
{ 0x62, SDLK_F7, 0 },
|
||||
{ 0x64, SDLK_F8, 0 },
|
||||
{ 0x65, SDLK_F9, 0 },
|
||||
{ 0x6d, SDLK_F10, 0 },
|
||||
{ 0x67, SDLK_F11, 0 },
|
||||
{ 0x6f, SDLK_F12, 0 },
|
||||
{ 0x69, SDLK_F13, 0 },
|
||||
{ 0x6b, SDLK_F14, 0 },
|
||||
{ 0x71, SDLK_F15, 0 },
|
||||
{ 0x7f, SDLK_PAUSE, 0 },
|
||||
{ 0x32, '`', '~' }, /* Key number 18? */
|
||||
{ 0x12, '1', '!' },
|
||||
{ 0x13, '2', '@' },
|
||||
{ 0x14, '3', '#' },
|
||||
{ 0x15, '4', '$' },
|
||||
{ 0x17, '5', '%' },
|
||||
{ 0x16, '6', '^' },
|
||||
{ 0x1a, '7', '&' },
|
||||
{ 0x1c, '8', '*' },
|
||||
{ 0x19, '9', '(' },
|
||||
{ 0x1d, '0', ')' },
|
||||
{ 0x1b, '-', '_' },
|
||||
{ 0x18, '=', '+' },
|
||||
{ 0x33, SDLK_BACKSPACE, 0 },
|
||||
{ 0x72, SDLK_INSERT, 0 }, /* Help? XK_Help */
|
||||
{ 0x32, '`', '~' }, /* Key number 18? */
|
||||
{ 0x12, '1', '!' },
|
||||
{ 0x13, '2', '@' },
|
||||
{ 0x14, '3', '#' },
|
||||
{ 0x15, '4', '$' },
|
||||
{ 0x17, '5', '%' },
|
||||
{ 0x16, '6', '^' },
|
||||
{ 0x1a, '7', '&' },
|
||||
{ 0x1c, '8', '*' },
|
||||
{ 0x19, '9', '(' },
|
||||
{ 0x1d, '0', ')' },
|
||||
{ 0x1b, '-', '_' },
|
||||
{ 0x18, '=', '+' },
|
||||
{ 0x33, SDLK_BACKSPACE, 0 },
|
||||
{ 0x72, SDLK_INSERT, 0 }, /* Help? XK_Help */
|
||||
/* { 0x73, XK_Home, 0 }, alias XK_Home to be XK_KP_Equal! */
|
||||
{ 0x74, SDLK_PAGEUP, 0 },
|
||||
{ 0x47, SDLK_NUMLOCKCLEAR, 0 }, /* Clear, XK_Clear */
|
||||
{ 0x51, SDLK_KP_EQUALS, 0 }, /* Note XK_Home alias! XK_Home */
|
||||
{ 0x4b, SDLK_KP_DIVIDE, 0 },
|
||||
{ 0x43, SDLK_KP_MULTIPLY, 0 },
|
||||
{ 0x30, SDLK_TAB, 0 },
|
||||
{ 0x0c, 'q', 'Q' },
|
||||
{ 0x0d, 'w', 'W' },
|
||||
{ 0x0e, 'e', 'E' },
|
||||
{ 0x0f, 'r', 'R' },
|
||||
{ 0x11, 't', 'T' },
|
||||
{ 0x10, 'y', 'Y' },
|
||||
{ 0x20, 'u', 'U' },
|
||||
{ 0x22, 'i', 'I' },
|
||||
{ 0x1f, 'o', 'O' },
|
||||
{ 0x23, 'p', 'P' },
|
||||
{ 0x21, '[', '{' },
|
||||
{ 0x1e, ']', '}' },
|
||||
{ 0x2a, 0x5c, '|' }, /* backslash, bar */
|
||||
{ 0x75, SDLK_DELETE, 0 },
|
||||
{ 0x77, SDLK_END, 0 },
|
||||
{ 0x79, SDLK_PAGEDOWN, 0 },
|
||||
{ 0x59, SDLK_KP_7, SDLK_HOME },
|
||||
{ 0x5b, SDLK_KP_8, SDLK_UP },
|
||||
{ 0x5c, SDLK_KP_9, SDLK_PAGEUP },
|
||||
{ 0x4e, SDLK_KP_MINUS, 0 },
|
||||
{ 0x39, SDLK_CAPSLOCK, 0 },
|
||||
{ 0x00, 'a', 'A' },
|
||||
{ 0x01, 's', 'S' },
|
||||
{ 0x02, 'd', 'D' },
|
||||
{ 0x03, 'f', 'F' },
|
||||
{ 0x05, 'g', 'G' },
|
||||
{ 0x04, 'h', 'H' },
|
||||
{ 0x26, 'j', 'J' },
|
||||
{ 0x28, 'k', 'K' },
|
||||
{ 0x25, 'l', 'L' },
|
||||
{ 0x29, ';', ':' },
|
||||
{ 0x27, 0x27, '"' }, /* single quote */
|
||||
{ 0x24, SDLK_RETURN, 0 },
|
||||
{ 0x56, SDLK_KP_4, SDLK_LEFT},
|
||||
{ 0x57, SDLK_KP_5, 0 },
|
||||
{ 0x58, SDLK_KP_6, SDLK_RIGHT },
|
||||
{ 0x45, SDLK_KP_PLUS, 0 },
|
||||
{ 0x38, SDLK_LSHIFT, SDLK_RSHIFT },
|
||||
{ 0x06, 'z', 'Z' },
|
||||
{ 0x07, 'x', 'X' },
|
||||
{ 0x08, 'c', 'C' },
|
||||
{ 0x09, 'v', 'V' },
|
||||
{ 0x0b, 'b', 'B' },
|
||||
{ 0x2d, 'n', 'N' },
|
||||
{ 0x2e, 'm', 'M' },
|
||||
{ 0x2b, ',', '<' },
|
||||
{ 0x2f, '.', '>' },
|
||||
{ 0x2c, '/', '?' },
|
||||
{ 0x3e, SDLK_UP, 0 },
|
||||
{ 0x53, SDLK_KP_1, 0 },
|
||||
{ 0x54, SDLK_KP_2, SDLK_DOWN },
|
||||
{ 0x55, SDLK_KP_3, SDLK_PAGEDOWN },
|
||||
{ 0x36, SDLK_RCTRL, SDLK_LCTRL },
|
||||
{ 0x3a, SDLK_LALT, SDLK_RALT }, /* Option */
|
||||
{ 0x37, SDLK_LGUI, SDLK_RGUI }, /* Command */
|
||||
{ 0x31, ' ', 0 },
|
||||
{ 0x3b, SDLK_LEFT, 0 },
|
||||
{ 0x3d, SDLK_DOWN, 0 },
|
||||
{ 0x3c, SDLK_RIGHT, 0 },
|
||||
{ 0x52, SDLK_KP_0, 0 },
|
||||
{ 0x41, SDLK_KP_PERIOD, 0 },
|
||||
{ 0x4c, SDLK_KP_ENTER, 0 },
|
||||
{ 0x74, SDLK_PAGEUP, 0 },
|
||||
{ 0x47, SDLK_NUMLOCKCLEAR, 0 }, /* Clear, XK_Clear */
|
||||
{ 0x51, SDLK_KP_EQUALS, 0 }, /* Note XK_Home alias! XK_Home */
|
||||
{ 0x4b, SDLK_KP_DIVIDE, 0 },
|
||||
{ 0x43, SDLK_KP_MULTIPLY, 0 },
|
||||
{ 0x30, SDLK_TAB, 0 },
|
||||
{ 0x0c, 'q', 'Q' },
|
||||
{ 0x0d, 'w', 'W' },
|
||||
{ 0x0e, 'e', 'E' },
|
||||
{ 0x0f, 'r', 'R' },
|
||||
{ 0x11, 't', 'T' },
|
||||
{ 0x10, 'y', 'Y' },
|
||||
{ 0x20, 'u', 'U' },
|
||||
{ 0x22, 'i', 'I' },
|
||||
{ 0x1f, 'o', 'O' },
|
||||
{ 0x23, 'p', 'P' },
|
||||
{ 0x21, '[', '{' },
|
||||
{ 0x1e, ']', '}' },
|
||||
{ 0x2a, 0x5c, '|' }, /* backslash, bar */
|
||||
{ 0x75, SDLK_DELETE, 0 },
|
||||
{ 0x77, SDLK_END, 0 },
|
||||
{ 0x79, SDLK_PAGEDOWN, 0 },
|
||||
{ 0x59, SDLK_KP_7, SDLK_HOME },
|
||||
{ 0x5b, SDLK_KP_8, SDLK_UP },
|
||||
{ 0x5c, SDLK_KP_9, SDLK_PAGEUP },
|
||||
{ 0x4e, SDLK_KP_MINUS, 0 },
|
||||
{ 0x39, SDLK_CAPSLOCK, 0 },
|
||||
{ 0x00, 'a', 'A' },
|
||||
{ 0x01, 's', 'S' },
|
||||
{ 0x02, 'd', 'D' },
|
||||
{ 0x03, 'f', 'F' },
|
||||
{ 0x05, 'g', 'G' },
|
||||
{ 0x04, 'h', 'H' },
|
||||
{ 0x26, 'j', 'J' },
|
||||
{ 0x28, 'k', 'K' },
|
||||
{ 0x25, 'l', 'L' },
|
||||
{ 0x29, ';', ':' },
|
||||
{ 0x27, 0x27, '"' }, /* single quote */
|
||||
{ 0x24, SDLK_RETURN, 0 },
|
||||
{ 0x56, SDLK_KP_4, SDLK_LEFT},
|
||||
{ 0x57, SDLK_KP_5, 0 },
|
||||
{ 0x58, SDLK_KP_6, SDLK_RIGHT },
|
||||
{ 0x45, SDLK_KP_PLUS, 0 },
|
||||
{ 0x38, SDLK_LSHIFT, SDLK_RSHIFT },
|
||||
{ 0x06, 'z', 'Z' },
|
||||
{ 0x07, 'x', 'X' },
|
||||
{ 0x08, 'c', 'C' },
|
||||
{ 0x09, 'v', 'V' },
|
||||
{ 0x0b, 'b', 'B' },
|
||||
{ 0x2d, 'n', 'N' },
|
||||
{ 0x2e, 'm', 'M' },
|
||||
{ 0x2b, ',', '<' },
|
||||
{ 0x2f, '.', '>' },
|
||||
{ 0x2c, '/', '?' },
|
||||
{ 0x3e, SDLK_UP, 0 },
|
||||
{ 0x53, SDLK_KP_1, 0 },
|
||||
{ 0x54, SDLK_KP_2, SDLK_DOWN },
|
||||
{ 0x55, SDLK_KP_3, SDLK_PAGEDOWN },
|
||||
{ 0x36, SDLK_RCTRL, SDLK_LCTRL },
|
||||
{ 0x3a, SDLK_LALT, SDLK_RALT }, /* Option */
|
||||
{ 0x37, SDLK_LGUI, SDLK_RGUI }, /* Command */
|
||||
{ 0x31, ' ', 0 },
|
||||
{ 0x3b, SDLK_LEFT, 0 },
|
||||
{ 0x3d, SDLK_DOWN, 0 },
|
||||
{ 0x3c, SDLK_RIGHT, 0 },
|
||||
{ 0x52, SDLK_KP_0, 0 },
|
||||
{ 0x41, SDLK_KP_PERIOD, 0 },
|
||||
{ 0x4c, SDLK_KP_ENTER, 0 },
|
||||
{ -1, -1, -1 }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int main(int argc, char **argv) {
|
||||
return gsplusmain(argc, argv);
|
||||
}
|
||||
|
||||
|
@ -225,12 +224,12 @@ SDL_bool IsFullScreen(SDL_Window *win) {
|
|||
|
||||
|
||||
void dev_video_init() {
|
||||
word32 lores_col;
|
||||
word32 lores_col;
|
||||
|
||||
// build keycode map ??
|
||||
g_num_a2_keycodes = 0;
|
||||
int i;
|
||||
int keycode;
|
||||
int i;
|
||||
int keycode;
|
||||
|
||||
for(i = 0; i < 0x7f; i++) {
|
||||
keycode = a2_key_to_sdlkeycode[i][0];
|
||||
|
@ -310,15 +309,14 @@ void dev_video_init_sdl() {
|
|||
|
||||
|
||||
window = SDL_CreateWindow(
|
||||
window_title, // window title (GSport vX.X)
|
||||
// SDL_WINDOWPOS_UNDEFINED, // initial x position
|
||||
// SDL_WINDOWPOS_UNDEFINED, // initial y position
|
||||
startx, starty,
|
||||
window_title, // window title (GSport vX.X)
|
||||
startx,
|
||||
starty,
|
||||
BASE_WINDOW_WIDTH, // width, in pixels
|
||||
X_A2_WINDOW_HEIGHT, // height, in pixels
|
||||
SDL_WINDOW_OPENGL // flags - see below
|
||||
| more_flags
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
// Check that the window was successfully created
|
||||
|
@ -340,16 +338,16 @@ void dev_video_init_sdl() {
|
|||
SDL_RenderSetLogicalSize(renderer, BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT);
|
||||
|
||||
texture = SDL_CreateTexture(renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT);
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT);
|
||||
// The window is open: could enter program loop here (see SDL_PollEvent())
|
||||
//overlay test
|
||||
overlay_texture = SDL_CreateTexture(renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
BASE_WINDOW_WIDTH,
|
||||
X_A2_WINDOW_HEIGHT);
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
BASE_WINDOW_WIDTH,
|
||||
X_A2_WINDOW_HEIGHT);
|
||||
|
||||
SDL_SetTextureBlendMode(overlay_texture, SDL_BLENDMODE_BLEND);
|
||||
overlay_pixels = malloc(BASE_WINDOW_WIDTH*X_A2_WINDOW_HEIGHT*sizeof(Uint32));
|
||||
|
@ -384,15 +382,6 @@ void dev_video_init_sdl() {
|
|||
|
||||
// Copy a rect to our SDL window
|
||||
void sdl_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height) {
|
||||
// FPS shiz
|
||||
currentTime = SDL_GetTicks();
|
||||
if (currentTime > lastTime + 1000) {
|
||||
printf("FPS: %d\n", frames);
|
||||
frames = 0;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
frames++;
|
||||
|
||||
|
||||
byte *src_ptr;
|
||||
int pixel_size = 4;
|
||||
|
@ -436,9 +425,9 @@ void set_refresh_needed() {
|
|||
|
||||
void x_get_kimage(Kimage *kimage_ptr) {
|
||||
byte *data;
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
|
@ -455,7 +444,7 @@ void check_input_events() {
|
|||
|
||||
|
||||
void check_input_events_sdl() {
|
||||
int motion = 0;
|
||||
int motion = 0;
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
|
@ -463,7 +452,7 @@ void check_input_events_sdl() {
|
|||
if (event.type == SDL_WINDOWEVENT) {
|
||||
set_refresh_needed();
|
||||
}
|
||||
switch( event.type ){
|
||||
switch( event.type ) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
handle_sdl_key_event(event);
|
||||
|
@ -486,7 +475,7 @@ void check_input_events_sdl() {
|
|||
cfg_inspect_maybe_insert_file(file, 0);
|
||||
SDL_free(file);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -495,7 +484,7 @@ void check_input_events_sdl() {
|
|||
|
||||
|
||||
int sdl_keysym_to_a2code(int keysym, int is_up) {
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if(keysym == 0) {
|
||||
return -1;
|
||||
|
@ -526,7 +515,7 @@ int sdl_keysym_to_a2code(int keysym, int is_up) {
|
|||
/* Look up Apple 2 keycode */
|
||||
for(i = g_num_a2_keycodes - 1; i >= 0; i--) {
|
||||
if((keysym == a2_key_to_sdlkeycode[i][1]) ||
|
||||
(keysym == a2_key_to_sdlkeycode[i][2])) {
|
||||
(keysym == a2_key_to_sdlkeycode[i][2])) {
|
||||
return a2_key_to_sdlkeycode[i][0];
|
||||
}
|
||||
}
|
||||
|
@ -536,9 +525,9 @@ int sdl_keysym_to_a2code(int keysym, int is_up) {
|
|||
|
||||
|
||||
void handle_sdl_key_event(SDL_Event event) {
|
||||
int state_xor;
|
||||
int state_xor;
|
||||
int state = 0;
|
||||
int is_up;
|
||||
int is_up;
|
||||
|
||||
int mod = event.key.keysym.mod;
|
||||
|
||||
|
@ -548,11 +537,11 @@ void handle_sdl_key_event(SDL_Event event) {
|
|||
|
||||
// when mod key is first press, comes as event, otherwise just a modifier
|
||||
if( mod & KMOD_LCTRL || mod & KMOD_RCTRL ||
|
||||
event.type == (SDL_KEYDOWN && (event.key.keysym.sym == SDLK_LCTRL || event.key.keysym.sym == SDLK_RCTRL))) {
|
||||
state = state | ControlMask;
|
||||
event.type == (SDL_KEYDOWN && (event.key.keysym.sym == SDLK_LCTRL || event.key.keysym.sym == SDLK_RCTRL))) {
|
||||
state = state | ControlMask;
|
||||
}
|
||||
if( (mod & KMOD_LSHIFT) || (mod & KMOD_RSHIFT) ||
|
||||
event.type == (SDL_KEYDOWN && (event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT))) {
|
||||
event.type == (SDL_KEYDOWN && (event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT))) {
|
||||
state = state | ShiftMask;
|
||||
}
|
||||
if( mod & KMOD_CAPS) {
|
||||
|
@ -581,7 +570,7 @@ void handle_sdl_key_event(SDL_Event event) {
|
|||
if (event.type == SDL_KEYUP) {
|
||||
is_up = 1;
|
||||
}
|
||||
switch( event.key.keysym.sym ){
|
||||
switch( event.key.keysym.sym ) {
|
||||
case SDLK_F11:
|
||||
if (kb_shift_control_state & ShiftMask) { // SHIFT+F11
|
||||
if (!is_up) {
|
||||
|
@ -623,7 +612,7 @@ int handle_sdl_mouse_motion_event(SDL_Event event) {
|
|||
x = event.motion.x - BASE_MARGIN_LEFT;
|
||||
y = event.motion.y - BASE_MARGIN_TOP;
|
||||
if (event.type == SDL_MOUSEBUTTONUP) {
|
||||
return update_mouse(x, y, 0 , event.motion.state &7 );
|
||||
return update_mouse(x, y, 0, event.motion.state &7 );
|
||||
} else {
|
||||
return update_mouse(x, y, event.motion.state, event.motion.state &7 );
|
||||
}
|
||||
|
@ -708,13 +697,13 @@ void x_take_screenshot() {
|
|||
SDL_FreeSurface(sshot);
|
||||
|
||||
SDL_Surface *s = SDL_CreateRGBSurface(0, BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
|
||||
if (s) {
|
||||
SDL_Surface * image = SDL_LoadBMP("screenshot.bmp");
|
||||
IMG_SavePNG(image, screenshot_filename);
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
SDL_FreeSurface(s);
|
||||
if (s) {
|
||||
SDL_Surface * image = SDL_LoadBMP("screenshot.bmp");
|
||||
IMG_SavePNG(image, screenshot_filename);
|
||||
SDL_FreeSurface(image);
|
||||
}
|
||||
SDL_FreeSurface(s);
|
||||
}
|
||||
|
||||
|
||||
void clipboard_paste(void) {
|
||||
|
@ -741,7 +730,7 @@ int clipboard_get_char(void) {
|
|||
char c;
|
||||
|
||||
if (!g_clipboard)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
/* skip utf-8 characters. */
|
||||
do {
|
||||
|
@ -750,7 +739,7 @@ int clipboard_get_char(void) {
|
|||
|
||||
/* windows -- skip the \n in \r\n. */
|
||||
if (c == '\r' && g_clipboard[g_clipboard_pos] == '\n')
|
||||
g_clipboard_pos++;
|
||||
g_clipboard_pos++;
|
||||
|
||||
/* everybody else -- convert \n to \r */
|
||||
if (c == '\n') c = '\r';
|
||||
|
@ -788,7 +777,7 @@ void x_auto_repeat_off(int must) { }
|
|||
void x_release_kimage(Kimage* kimage_ptr) { }
|
||||
// OG Addding ratio
|
||||
int x_calc_ratio(float x,float y) { return 1; }
|
||||
void x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int *shift_right_ptr) { return; }
|
||||
void x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int *shift_right_ptr) { return; }
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb) { }
|
||||
void x_update_physical_colormap() { }
|
||||
void show_xcolor_array() { }
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include "defc.h"
|
||||
#include "glog.h"
|
||||
#include "sound.h"
|
||||
#include <assert.h>
|
||||
extern word32 *g_sound_shm_addr;
|
||||
extern int g_sound_shm_pos;
|
||||
extern int g_audio_enable;
|
||||
extern word32 *g_sound_shm_addr;
|
||||
extern int g_sound_shm_pos;
|
||||
extern int g_audio_enable;
|
||||
extern int g_preferred_rate;
|
||||
|
||||
static byte *playbuf = 0;
|
||||
|
@ -29,187 +29,179 @@ static int g_zeroes_seen;
|
|||
SDL_AudioDeviceID dev = 0;
|
||||
|
||||
|
||||
void sdlsnd_init(word32 *shmaddr)
|
||||
{
|
||||
void sdlsnd_init(word32 *shmaddr) {
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
glog("Could not initialize SDL2 audio");
|
||||
g_audio_enable = 0;
|
||||
} else {
|
||||
glog("SDL2 audio initialized");
|
||||
}
|
||||
glog("Could not initialize SDL2 audio");
|
||||
g_audio_enable = 0;
|
||||
} else {
|
||||
glog("SDL2 audio initialized");
|
||||
}
|
||||
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sound_write_sdl(int real_samps, int size)
|
||||
{
|
||||
void sound_write_sdl(int real_samps, int size) {
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
int shm_read;
|
||||
int shm_read;
|
||||
|
||||
if (real_samps) {
|
||||
shm_read = (g_sound_shm_pos - size + SOUND_SHM_SAMP_SIZE)%SOUND_SHM_SAMP_SIZE;
|
||||
SDL_LockAudioDevice(dev);
|
||||
while(size > 0) {
|
||||
if(g_playbuf_buffered >= snd_buf) {
|
||||
printf("sound_write_sdl failed @%d, %d buffered, %d samples skipped\n",snd_write,g_playbuf_buffered, size);
|
||||
shm_read += size;
|
||||
shm_read %= SOUND_SHM_SAMP_SIZE;
|
||||
size = 0;
|
||||
} else {
|
||||
((word32*)playbuf)[snd_write/SAMPLE_CHAN_SIZE] = g_sound_shm_addr[shm_read];
|
||||
shm_read++;
|
||||
if (shm_read >= SOUND_SHM_SAMP_SIZE)
|
||||
shm_read = 0;
|
||||
snd_write += SAMPLE_CHAN_SIZE;
|
||||
if (snd_write >= snd_buf)
|
||||
snd_write = 0;
|
||||
size--;
|
||||
g_playbuf_buffered += SAMPLE_CHAN_SIZE;
|
||||
}
|
||||
}
|
||||
if (real_samps) {
|
||||
shm_read = (g_sound_shm_pos - size + SOUND_SHM_SAMP_SIZE)%SOUND_SHM_SAMP_SIZE;
|
||||
SDL_LockAudioDevice(dev);
|
||||
while(size > 0) {
|
||||
if(g_playbuf_buffered >= snd_buf) {
|
||||
printf("sound_write_sdl failed @%d, %d buffered, %d samples skipped\n",snd_write,g_playbuf_buffered, size);
|
||||
shm_read += size;
|
||||
shm_read %= SOUND_SHM_SAMP_SIZE;
|
||||
size = 0;
|
||||
} else {
|
||||
((word32*)playbuf)[snd_write/SAMPLE_CHAN_SIZE] = g_sound_shm_addr[shm_read];
|
||||
shm_read++;
|
||||
if (shm_read >= SOUND_SHM_SAMP_SIZE)
|
||||
shm_read = 0;
|
||||
snd_write += SAMPLE_CHAN_SIZE;
|
||||
if (snd_write >= snd_buf)
|
||||
snd_write = 0;
|
||||
size--;
|
||||
g_playbuf_buffered += SAMPLE_CHAN_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf);
|
||||
assert(g_sound_shm_pos == shm_read);
|
||||
SDL_UnlockAudioDevice(dev);
|
||||
}
|
||||
if(g_sound_paused && (g_playbuf_buffered > 0)) {
|
||||
glogf("Unpausing sound, %d buffered",g_playbuf_buffered);
|
||||
g_sound_paused = 0;
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
}
|
||||
if(!g_sound_paused && (g_playbuf_buffered <= 0)) {
|
||||
glog("Pausing sound");
|
||||
g_sound_paused = 1;
|
||||
SDL_PauseAudioDevice(dev, 1);
|
||||
}
|
||||
assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf);
|
||||
assert(g_sound_shm_pos == shm_read);
|
||||
SDL_UnlockAudioDevice(dev);
|
||||
}
|
||||
if(g_sound_paused && (g_playbuf_buffered > 0)) {
|
||||
glogf("Unpausing sound, %d buffered",g_playbuf_buffered);
|
||||
g_sound_paused = 0;
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
}
|
||||
if(!g_sound_paused && (g_playbuf_buffered <= 0)) {
|
||||
glog("Pausing sound");
|
||||
g_sound_paused = 1;
|
||||
SDL_PauseAudioDevice(dev, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
/* Callback for sound */
|
||||
static void _snd_callback(void* userdata, Uint8 *stream, int len)
|
||||
{
|
||||
int i;
|
||||
/* Slurp off the play buffer */
|
||||
assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf);
|
||||
/*printf("slurp %d, %d buffered\n",len, g_playbuf_buffered);*/
|
||||
for(i = 0; i < len; ++i) {
|
||||
if(g_playbuf_buffered <= 0) {
|
||||
stream[i] = 0;
|
||||
} else {
|
||||
stream[i] = playbuf[snd_read++];
|
||||
if(snd_read == snd_buf)
|
||||
snd_read = 0;
|
||||
g_playbuf_buffered--;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (g_playbuf_buffered <= 0) {
|
||||
printf("snd_callback: buffer empty, Pausing sound\n");
|
||||
g_sound_paused = 1;
|
||||
SDL_PauseAudio(1);
|
||||
}
|
||||
#endif
|
||||
//printf("end slurp %d, %d buffered\n",len, g_playbuf_buffered);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
long
|
||||
sound_init_device_sdl()
|
||||
{
|
||||
#ifdef HAVE_SDL
|
||||
long rate;
|
||||
SDL_AudioSpec wanted;
|
||||
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
glogf("SDL2 Couldn't init SDL_INIT_AUDIO: %s!", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the desired format */
|
||||
wanted.freq = g_preferred_rate;
|
||||
wanted.format = AUDIO_S16SYS;
|
||||
wanted.channels = NUM_CHANNELS;
|
||||
wanted.samples = 512;
|
||||
wanted.callback = _snd_callback;
|
||||
wanted.userdata = NULL;
|
||||
|
||||
/* Open audio, and get the real spec */
|
||||
dev = SDL_OpenAudioDevice(NULL, 0, &wanted, &spec, 0);
|
||||
if (dev == 0) {
|
||||
glogf("SDL2 Couldn't open audio: %s!", SDL_GetError());
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return 0;
|
||||
|
||||
static void _snd_callback(void* userdata, Uint8 *stream, int len) {
|
||||
int i;
|
||||
/* Slurp off the play buffer */
|
||||
assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf);
|
||||
/*printf("slurp %d, %d buffered\n",len, g_playbuf_buffered);*/
|
||||
for(i = 0; i < len; ++i) {
|
||||
if(g_playbuf_buffered <= 0) {
|
||||
stream[i] = 0;
|
||||
} else {
|
||||
glogf("SDL2 opened audio device: %d", dev);
|
||||
stream[i] = playbuf[snd_read++];
|
||||
if(snd_read == snd_buf)
|
||||
snd_read = 0;
|
||||
g_playbuf_buffered--;
|
||||
}
|
||||
|
||||
/* Check everything */
|
||||
if(spec.channels != wanted.channels) {
|
||||
glogf("SDL2 Warning, couldn't get stereo audio format!");
|
||||
//goto snd_error;
|
||||
}
|
||||
if(spec.format != wanted.format) {
|
||||
glog("SDL2 Warning, couldn't get a supported audio format!");
|
||||
glogf("SDL2 wanted %X, got %X",wanted.format,spec.format);
|
||||
//goto snd_error;
|
||||
}
|
||||
if(spec.freq != wanted.freq) {
|
||||
glogf("SDL2 wanted rate = %d, got rate = %d", wanted.freq, spec.freq);
|
||||
}
|
||||
/* Set things as they really are */
|
||||
rate = spec.freq;
|
||||
|
||||
snd_buf = SOUND_SHM_SAMP_SIZE*SAMPLE_CHAN_SIZE;
|
||||
playbuf = (byte*) malloc(snd_buf);
|
||||
if (!playbuf)
|
||||
goto snd_error;
|
||||
g_playbuf_buffered = 0;
|
||||
|
||||
glogf("SDL2 sound shared memory size=%d", SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE);
|
||||
|
||||
g_sound_shm_addr = malloc(SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE);
|
||||
memset(g_sound_shm_addr,0,SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE);
|
||||
|
||||
/* It's all good! */
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
/* Let's start playing sound */
|
||||
g_sound_paused = 0;
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
|
||||
set_audio_rate(rate);
|
||||
return rate;
|
||||
|
||||
snd_error:
|
||||
/* Oops! Something bad happened, cleanup. */
|
||||
SDL_CloseAudioDevice(dev);
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
if(playbuf)
|
||||
free((void*)playbuf);
|
||||
playbuf = 0;
|
||||
snd_buf = 0;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
if (g_playbuf_buffered <= 0) {
|
||||
printf("snd_callback: buffer empty, Pausing sound\n");
|
||||
g_sound_paused = 1;
|
||||
SDL_PauseAudio(1);
|
||||
}
|
||||
#endif
|
||||
//printf("end slurp %d, %d buffered\n",len, g_playbuf_buffered);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
sound_shutdown_sdl()
|
||||
{
|
||||
|
||||
|
||||
|
||||
long sound_init_device_sdl() {
|
||||
#ifdef HAVE_SDL
|
||||
SDL_CloseAudioDevice(dev);
|
||||
if(playbuf)
|
||||
free((void*)playbuf);
|
||||
playbuf = 0;
|
||||
long rate;
|
||||
SDL_AudioSpec wanted;
|
||||
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
glogf("SDL2 Couldn't init SDL_INIT_AUDIO: %s!", SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the desired format */
|
||||
wanted.freq = g_preferred_rate;
|
||||
wanted.format = AUDIO_S16SYS;
|
||||
wanted.channels = NUM_CHANNELS;
|
||||
wanted.samples = 512;
|
||||
wanted.callback = _snd_callback;
|
||||
wanted.userdata = NULL;
|
||||
|
||||
/* Open audio, and get the real spec */
|
||||
dev = SDL_OpenAudioDevice(NULL, 0, &wanted, &spec, 0);
|
||||
if (dev == 0) {
|
||||
glogf("SDL2 Couldn't open audio: %s!", SDL_GetError());
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
glogf("SDL2 opened audio device: %d", dev);
|
||||
}
|
||||
|
||||
/* Check everything */
|
||||
if(spec.channels != wanted.channels) {
|
||||
glogf("SDL2 Warning, couldn't get stereo audio format!");
|
||||
//goto snd_error;
|
||||
}
|
||||
if(spec.format != wanted.format) {
|
||||
glog("SDL2 Warning, couldn't get a supported audio format!");
|
||||
glogf("SDL2 wanted %X, got %X",wanted.format,spec.format);
|
||||
//goto snd_error;
|
||||
}
|
||||
if(spec.freq != wanted.freq) {
|
||||
glogf("SDL2 wanted rate = %d, got rate = %d", wanted.freq, spec.freq);
|
||||
}
|
||||
/* Set things as they really are */
|
||||
rate = spec.freq;
|
||||
|
||||
snd_buf = SOUND_SHM_SAMP_SIZE*SAMPLE_CHAN_SIZE;
|
||||
playbuf = (byte*) malloc(snd_buf);
|
||||
if (!playbuf)
|
||||
goto snd_error;
|
||||
g_playbuf_buffered = 0;
|
||||
|
||||
glogf("SDL2 sound shared memory size=%d", SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE);
|
||||
|
||||
g_sound_shm_addr = malloc(SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE);
|
||||
memset(g_sound_shm_addr,0,SOUND_SHM_SAMP_SIZE * SAMPLE_CHAN_SIZE);
|
||||
|
||||
/* It's all good! */
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
/* Let's start playing sound */
|
||||
g_sound_paused = 0;
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
|
||||
set_audio_rate(rate);
|
||||
return rate;
|
||||
|
||||
snd_error:
|
||||
/* Oops! Something bad happened, cleanup. */
|
||||
SDL_CloseAudioDevice(dev);
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
if(playbuf)
|
||||
free((void*)playbuf);
|
||||
playbuf = 0;
|
||||
snd_buf = 0;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sound_shutdown_sdl() {
|
||||
#ifdef HAVE_SDL
|
||||
SDL_CloseAudioDevice(dev);
|
||||
if(playbuf)
|
||||
free((void*)playbuf);
|
||||
playbuf = 0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "defc.h"
|
||||
|
@ -18,7 +18,7 @@ extern int g_audio_rate;
|
|||
unsigned int __stdcall child_sound_loop_win32(void *param);
|
||||
void check_wave_error(int res, char *str);
|
||||
|
||||
#define NUM_WAVE_HEADERS 8
|
||||
#define NUM_WAVE_HEADERS 8
|
||||
|
||||
//HWAVEOUT g_wave_handle = NULL; // OG Default value must be set
|
||||
//WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
|
||||
|
@ -27,7 +27,7 @@ extern int g_audio_enable;
|
|||
extern word32 *g_sound_shm_addr;
|
||||
extern int g_preferred_rate;
|
||||
|
||||
int g_sdlsnd_buflen = 0x1000;
|
||||
int g_sdlsnd_buflen = 0x1000;
|
||||
word32 *bptr = NULL;
|
||||
int g_sdlsnd_write_idx;
|
||||
int g_sdlsnd_read_idx;
|
||||
|
@ -55,13 +55,12 @@ static void sound_write_sdl(int real_samps, int size);
|
|||
|
||||
#endif
|
||||
|
||||
void sdlsnd_init(word32 *shmaddr)
|
||||
{
|
||||
void sdlsnd_init(word32 *shmaddr) {
|
||||
printf("sdlsnd_init\n");
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
printf("Cannot initialize SDL audio\n");
|
||||
g_audio_enable = 0;
|
||||
}
|
||||
printf("Cannot initialize SDL audio\n");
|
||||
g_audio_enable = 0;
|
||||
}
|
||||
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
return;
|
||||
|
@ -70,17 +69,15 @@ void sdlsnd_init(word32 *shmaddr)
|
|||
|
||||
|
||||
|
||||
void
|
||||
win32snd_init(word32 *shmaddr)
|
||||
{
|
||||
printf("win32snd_init\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
void win32snd_init(word32 *shmaddr) {
|
||||
printf("win32snd_init\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sdl_send_audio(word32 *ptr, int size, int real_samps) {
|
||||
void sdl_send_audio(word32 *ptr, int size, int real_samps) {
|
||||
|
||||
/* code */
|
||||
//printf(" sdl_s_a %d\t 0x%08x ",size, &ptr);
|
||||
|
@ -103,16 +100,16 @@ void handle_sdl_snd(void *userdata, Uint8 *stream, int len) {
|
|||
/* Only play if we have data left */
|
||||
/* if ( g_playbuf_buffered == 0) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
for(int i = 0; i < len; ++i) {
|
||||
if(g_playbuf_buffered <= 0) {
|
||||
stream[i] = 0;
|
||||
stream[i] = 0;
|
||||
} else {
|
||||
stream[i] = bptr[g_sdlsnd_read_idx++];
|
||||
if(g_sdlsnd_read_idx == g_sdlsnd_buflen)
|
||||
g_sdlsnd_read_idx = 0;
|
||||
g_playbuf_buffered--;
|
||||
stream[i] = bptr[g_sdlsnd_read_idx++];
|
||||
if(g_sdlsnd_read_idx == g_sdlsnd_buflen)
|
||||
g_sdlsnd_read_idx = 0;
|
||||
g_playbuf_buffered--;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -128,15 +125,15 @@ void handle_sdl_snd(void *userdata, Uint8 *stream, int len) {
|
|||
g_playbuf_buffered -= len;
|
||||
} else {
|
||||
/*
|
||||
int top_len = 0;
|
||||
top_len = g_sdlsnd_buflen - g_sdlsnd_read_idx;
|
||||
SDL_memcpy (stream, &bptr[g_sdlsnd_read_idx], top_len);
|
||||
g_sdlsnd_read_idx = 0;
|
||||
g_playbuf_buffered -= top_len;
|
||||
// SDL_memcpy (stream+top_len, bptr[g_sdlsnd_read_idx], len-top_len);
|
||||
g_sdlsnd_read_idx += len-top_len;
|
||||
g_playbuf_buffered -= len-top_len;
|
||||
*/
|
||||
int top_len = 0;
|
||||
top_len = g_sdlsnd_buflen - g_sdlsnd_read_idx;
|
||||
SDL_memcpy (stream, &bptr[g_sdlsnd_read_idx], top_len);
|
||||
g_sdlsnd_read_idx = 0;
|
||||
g_playbuf_buffered -= top_len;
|
||||
// SDL_memcpy (stream+top_len, bptr[g_sdlsnd_read_idx], len-top_len);
|
||||
g_sdlsnd_read_idx += len-top_len;
|
||||
g_playbuf_buffered -= len-top_len;
|
||||
*/
|
||||
}
|
||||
|
||||
//SDL_MixAudio(stream, pointer, len, SDL_MIX_MAXVOLUME);
|
||||
|
@ -144,9 +141,7 @@ void handle_sdl_snd(void *userdata, Uint8 *stream, int len) {
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
child_sound_init_sdl()
|
||||
{
|
||||
void child_sound_init_sdl() {
|
||||
printf("child_sound_init_sdl");
|
||||
|
||||
SDL_memset(&want, 0, sizeof(want)); // or SDL_zero(want)
|
||||
|
@ -158,11 +153,11 @@ child_sound_init_sdl()
|
|||
|
||||
dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
|
||||
if (dev == 0) {
|
||||
printf("Failed to open audio: %s\n", SDL_GetError());
|
||||
printf("Failed to open audio: %s\n", SDL_GetError());
|
||||
} else {
|
||||
if (have.format != want.format) { // we let this one thing change.
|
||||
printf("We didn't get Float32 audio format.\n");
|
||||
}
|
||||
if (have.format != want.format) { // we let this one thing change.
|
||||
printf("We didn't get Float32 audio format.\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -185,16 +180,15 @@ child_sound_init_sdl()
|
|||
|
||||
SDL_PauseAudioDevice(dev, 0); // start audio playing.
|
||||
|
||||
g_audio_rate = have.freq;
|
||||
g_audio_rate = have.freq;
|
||||
printf("g_audio_rate: %d\n", g_audio_rate);
|
||||
set_audio_rate(g_audio_rate); // let kegs simulator know the rate
|
||||
set_audio_rate(g_audio_rate); // let kegs simulator know the rate
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
sdlsnd_shutdown() {
|
||||
void sdlsnd_shutdown() {
|
||||
//SDL_Delay(5000); // let the audio callback play some sound for 5 seconds.
|
||||
SDL_CloseAudioDevice(dev);
|
||||
printf("sdlsnd_shutdown");
|
||||
|
|
3505
src/sim65816.c
3505
src/sim65816.c
File diff suppressed because it is too large
Load Diff
1286
src/smartport.c
1286
src/smartport.c
File diff suppressed because it is too large
Load Diff
3075
src/sound.c
3075
src/sound.c
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include "sound.h"
|
||||
|
@ -21,7 +21,7 @@ long sound_init_device_sdl();
|
|||
# include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifndef WIN_SOUND /* Workaround - gcc in cygwin wasn't defining _WIN32 */
|
||||
#ifndef WIN_SOUND /* Workaround - gcc in cygwin wasn't defining _WIN32 */
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
|
@ -34,22 +34,22 @@ extern int Verbose;
|
|||
|
||||
extern int g_audio_rate;
|
||||
|
||||
int g_preferred_rate = 48000;
|
||||
int g_audio_socket = -1;
|
||||
int g_bytes_written = 0;
|
||||
int g_preferred_rate = 48000;
|
||||
int g_audio_socket = -1;
|
||||
int g_bytes_written = 0;
|
||||
|
||||
#define ZERO_BUF_SIZE 2048
|
||||
#define ZERO_BUF_SIZE 2048
|
||||
|
||||
word32 g_snd_zero_buf[ZERO_BUF_SIZE];
|
||||
|
||||
#define ZERO_PAUSE_SAFETY_SAMPS (g_audio_rate >> 5)
|
||||
#define ZERO_PAUSE_NUM_SAMPS (4*g_audio_rate)
|
||||
#define ZERO_PAUSE_SAFETY_SAMPS (g_audio_rate >> 5)
|
||||
#define ZERO_PAUSE_NUM_SAMPS (4*g_audio_rate)
|
||||
|
||||
int g_zeroes_buffered = 0;
|
||||
int g_zeroes_seen = 0;
|
||||
int g_sound_paused = 0;
|
||||
int g_childsnd_vbl = 0;
|
||||
int g_childsnd_pos = 0;
|
||||
int g_zeroes_buffered = 0;
|
||||
int g_zeroes_seen = 0;
|
||||
int g_sound_paused = 0;
|
||||
int g_childsnd_vbl = 0;
|
||||
int g_childsnd_pos = 0;
|
||||
word32 *g_childsnd_shm_addr = 0;
|
||||
|
||||
void child_sound_init_linux();
|
||||
|
@ -59,364 +59,352 @@ void child_sound_init_mac();
|
|||
void child_sound_init_sdl();
|
||||
long sound_init_device_sdl();
|
||||
|
||||
void
|
||||
reliable_buf_write(word32 *shm_addr, int pos, int size)
|
||||
{
|
||||
byte *ptr;
|
||||
int ret = 0;
|
||||
void reliable_buf_write(word32 *shm_addr, int pos, int size) {
|
||||
byte *ptr;
|
||||
int ret = 0;
|
||||
|
||||
if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE ||
|
||||
size > SOUND_SHM_SAMP_SIZE ||
|
||||
(pos + size) > SOUND_SHM_SAMP_SIZE) {
|
||||
printf("reliable_buf_write: pos: %04x, size: %04x\n", pos, size);
|
||||
exit(1);
|
||||
}
|
||||
if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE ||
|
||||
size > SOUND_SHM_SAMP_SIZE ||
|
||||
(pos + size) > SOUND_SHM_SAMP_SIZE) {
|
||||
printf("reliable_buf_write: pos: %04x, size: %04x\n", pos, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ptr = (byte *)&(shm_addr[pos]);
|
||||
size = size * 4;
|
||||
ptr = (byte *)&(shm_addr[pos]);
|
||||
size = size * 4;
|
||||
|
||||
while(size > 0) {
|
||||
while(size > 0) {
|
||||
#if defined(HAVE_SDL)
|
||||
//ret = sdl_send_audio(ptr, size);
|
||||
|
||||
#elif defined(WIN_SOUND)
|
||||
ret = win32_send_audio(ptr, size);
|
||||
ret = win32_send_audio(ptr, size);
|
||||
#elif defined(MAC) && !defined(HAVE_SDL)
|
||||
ret = mac_send_audio(ptr, size);
|
||||
ret = mac_send_audio(ptr, size);
|
||||
#else
|
||||
ret = write(g_audio_socket, ptr, size);
|
||||
ret = write(g_audio_socket, ptr, size);
|
||||
#endif
|
||||
|
||||
if(ret < 0) {
|
||||
printf("audio write, errno: %d\n", errno);
|
||||
exit(1);
|
||||
}
|
||||
size = size - ret;
|
||||
ptr += ret;
|
||||
g_bytes_written += ret;
|
||||
}
|
||||
if(ret < 0) {
|
||||
printf("audio write, errno: %d\n", errno);
|
||||
exit(1);
|
||||
}
|
||||
size = size - ret;
|
||||
ptr += ret;
|
||||
g_bytes_written += ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
reliable_zero_write(int amt)
|
||||
{
|
||||
int len;
|
||||
void reliable_zero_write(int amt) {
|
||||
int len;
|
||||
|
||||
while(amt > 0) {
|
||||
len = MIN(amt, ZERO_BUF_SIZE);
|
||||
reliable_buf_write(g_snd_zero_buf, 0, len);
|
||||
amt -= len;
|
||||
}
|
||||
while(amt > 0) {
|
||||
len = MIN(amt, ZERO_BUF_SIZE);
|
||||
reliable_buf_write(g_snd_zero_buf, 0, len);
|
||||
amt -= len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
child_sound_loop(int read_fd, int write_fd, word32 *shm_addr)
|
||||
{
|
||||
word32 tmp;
|
||||
int ret;
|
||||
void child_sound_loop(int read_fd, int write_fd, word32 *shm_addr) {
|
||||
word32 tmp;
|
||||
int ret;
|
||||
|
||||
g_audio_rate = g_preferred_rate;
|
||||
g_audio_rate = g_preferred_rate;
|
||||
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
g_sound_paused = 0;
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
g_sound_paused = 0;
|
||||
|
||||
g_childsnd_pos = 0;
|
||||
g_childsnd_vbl = 0;
|
||||
g_childsnd_shm_addr = shm_addr;
|
||||
g_childsnd_pos = 0;
|
||||
g_childsnd_vbl = 0;
|
||||
g_childsnd_shm_addr = shm_addr;
|
||||
|
||||
#if defined(HAVE_SDL)
|
||||
//child_sound_init_sdl();
|
||||
sound_init_device_sdl(); // ignores long return value of sample rate
|
||||
sound_init_device_sdl(); // ignores long return value of sample rate
|
||||
return;
|
||||
#elif defined(__linux__) || defined(OSS)
|
||||
child_sound_init_linux();
|
||||
child_sound_init_linux();
|
||||
#elif HPUX
|
||||
child_sound_init_hpdev();
|
||||
child_sound_init_hpdev();
|
||||
#elif WIN_SOUND
|
||||
child_sound_init_win32();
|
||||
return;
|
||||
child_sound_init_win32();
|
||||
return;
|
||||
#elif defined(MAC) && !defined(HAVE_SDL)
|
||||
child_sound_init_mac();
|
||||
return;
|
||||
child_sound_init_mac();
|
||||
return;
|
||||
#endif
|
||||
|
||||
doc_printf("Child pipe fd: %d\n", read_fd);
|
||||
doc_printf("Child pipe fd: %d\n", read_fd);
|
||||
|
||||
tmp = g_audio_rate;
|
||||
ret = write(write_fd, &tmp, 4);
|
||||
if(ret != 4) {
|
||||
printf("Unable to send back audio rate to parent\n");
|
||||
printf("ret: %d fd: %d, errno: %d\n", ret, write_fd, errno);
|
||||
exit(1);
|
||||
}
|
||||
printf("Wrote to fd %d the audio rate\n", write_fd);
|
||||
tmp = g_audio_rate;
|
||||
ret = write(write_fd, &tmp, 4);
|
||||
if(ret != 4) {
|
||||
printf("Unable to send back audio rate to parent\n");
|
||||
printf("ret: %d fd: %d, errno: %d\n", ret, write_fd, errno);
|
||||
exit(1);
|
||||
}
|
||||
printf("Wrote to fd %d the audio rate\n", write_fd);
|
||||
|
||||
close(write_fd);
|
||||
close(write_fd);
|
||||
|
||||
while(1) {
|
||||
errno = 0;
|
||||
ret = read(read_fd, (char*)&tmp, 4);
|
||||
if(ret <= 0) {
|
||||
printf("child dying from ret: %d, errno: %d\n",
|
||||
ret, errno);
|
||||
break;
|
||||
}
|
||||
while(1) {
|
||||
errno = 0;
|
||||
ret = read(read_fd, (char*)&tmp, 4);
|
||||
if(ret <= 0) {
|
||||
printf("child dying from ret: %d, errno: %d\n",
|
||||
ret, errno);
|
||||
break;
|
||||
}
|
||||
|
||||
child_sound_playit(tmp);
|
||||
}
|
||||
child_sound_playit(tmp);
|
||||
}
|
||||
|
||||
#ifdef HPUX
|
||||
ioctl(g_audio_socket, AUDIO_DRAIN, 0);
|
||||
ioctl(g_audio_socket, AUDIO_DRAIN, 0);
|
||||
#endif
|
||||
close(g_audio_socket);
|
||||
close(g_audio_socket);
|
||||
|
||||
exit(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// called by sound.c:send_sound()
|
||||
void
|
||||
child_sound_playit(word32 tmp)
|
||||
{
|
||||
int size;
|
||||
void child_sound_playit(word32 tmp) {
|
||||
int size;
|
||||
|
||||
size = tmp & 0xffffff;
|
||||
size = tmp & 0xffffff;
|
||||
|
||||
if((tmp >> 24) == 0xa2) {
|
||||
/* play sound here */
|
||||
if((tmp >> 24) == 0xa2) {
|
||||
/* play sound here */
|
||||
|
||||
|
||||
#if 0
|
||||
g_childsnd_pos += g_zeroes_buffered;
|
||||
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
|
||||
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
|
||||
}
|
||||
g_childsnd_pos += g_zeroes_buffered;
|
||||
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
|
||||
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(g_zeroes_buffered) {
|
||||
reliable_zero_write(g_zeroes_buffered);
|
||||
}
|
||||
if(g_zeroes_buffered) {
|
||||
reliable_zero_write(g_zeroes_buffered);
|
||||
}
|
||||
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
|
||||
// only write up to end of buffer
|
||||
if((size + g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) {
|
||||
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos,
|
||||
SOUND_SHM_SAMP_SIZE - g_childsnd_pos);
|
||||
size = (g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE;
|
||||
g_childsnd_pos = 0;
|
||||
}
|
||||
// only write up to end of buffer
|
||||
if((size + g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) {
|
||||
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos,
|
||||
SOUND_SHM_SAMP_SIZE - g_childsnd_pos);
|
||||
size = (g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE;
|
||||
g_childsnd_pos = 0;
|
||||
}
|
||||
|
||||
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos, size);
|
||||
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos, size);
|
||||
|
||||
if(g_sound_paused) {
|
||||
glogf("Unpausing sound, zb: %d\n", g_zeroes_buffered);
|
||||
g_sound_paused = 0;
|
||||
}
|
||||
if(g_sound_paused) {
|
||||
glogf("Unpausing sound, zb: %d\n", g_zeroes_buffered);
|
||||
g_sound_paused = 0;
|
||||
}
|
||||
|
||||
} else if((tmp >> 24) == 0xa1) {
|
||||
if(g_sound_paused) {
|
||||
if(g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) {
|
||||
g_zeroes_buffered += size;
|
||||
}
|
||||
} else {
|
||||
/* not paused, send it through */
|
||||
g_zeroes_seen += size;
|
||||
} else if((tmp >> 24) == 0xa1) {
|
||||
if(g_sound_paused) {
|
||||
if(g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) {
|
||||
g_zeroes_buffered += size;
|
||||
}
|
||||
} else {
|
||||
/* not paused, send it through */
|
||||
g_zeroes_seen += size;
|
||||
|
||||
reliable_zero_write(size);
|
||||
reliable_zero_write(size);
|
||||
|
||||
if(g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) {
|
||||
glog("Pausing sound");
|
||||
g_sound_paused = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("tmp received bad: %08x\n", tmp);
|
||||
exit(3);
|
||||
}
|
||||
if(g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) {
|
||||
glog("Pausing sound");
|
||||
g_sound_paused = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("tmp received bad: %08x\n", tmp);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
g_childsnd_pos += size;
|
||||
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
|
||||
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
|
||||
}
|
||||
g_childsnd_pos += size;
|
||||
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
|
||||
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
|
||||
}
|
||||
|
||||
g_childsnd_vbl++;
|
||||
if(g_childsnd_vbl >= 60) {
|
||||
g_childsnd_vbl = 0;
|
||||
g_bytes_written = 0;
|
||||
}
|
||||
g_childsnd_vbl++;
|
||||
if(g_childsnd_vbl >= 60) {
|
||||
g_childsnd_vbl = 0;
|
||||
g_bytes_written = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HPUX
|
||||
void
|
||||
child_sound_init_hpdev()
|
||||
{
|
||||
struct audio_describe audio_descr;
|
||||
int output_channel;
|
||||
char *str;
|
||||
int speaker;
|
||||
int ret;
|
||||
int i;
|
||||
void child_sound_init_hpdev() {
|
||||
struct audio_describe audio_descr;
|
||||
int output_channel;
|
||||
char *str;
|
||||
int speaker;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
g_audio_socket = open("/dev/audio", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/audio failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
g_audio_socket = open("/dev/audio", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/audio failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_DESCRIBE, &audio_descr);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_DESCRIBE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_DESCRIBE, &audio_descr);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_DESCRIBE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i = 0; i < audio_descr.nrates; i++) {
|
||||
printf("Audio rate[%d] = %d\n", i,
|
||||
audio_descr.sample_rate[i]);
|
||||
}
|
||||
for(i = 0; i < audio_descr.nrates; i++) {
|
||||
printf("Audio rate[%d] = %d\n", i,
|
||||
audio_descr.sample_rate[i]);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_DATA_FORMAT,
|
||||
AUDIO_FORMAT_LINEAR16BIT);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_DATA_FORMAT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_DATA_FORMAT,
|
||||
AUDIO_FORMAT_LINEAR16BIT);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_DATA_FORMAT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_CHANNELS, NUM_CHANNELS);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_CHANNELS failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_CHANNELS, NUM_CHANNELS);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_CHANNELS failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_TXBUFSIZE, 16*1024);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_TXBUFSIZE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_TXBUFSIZE, 16*1024);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_TXBUFSIZE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_SAMPLE_RATE, g_audio_rate);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_SAMPLE_RATE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_SAMPLE_RATE, g_audio_rate);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_SAMPLE_RATE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_GET_OUTPUT, &output_channel);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_GET_OUTPUT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_GET_OUTPUT, &output_channel);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_GET_OUTPUT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
speaker = 1;
|
||||
str = getenv("SPEAKER");
|
||||
if(str) {
|
||||
if(str[0] != 'i' && str[0] != 'I') {
|
||||
speaker = 0;
|
||||
}
|
||||
}
|
||||
speaker = 1;
|
||||
str = getenv("SPEAKER");
|
||||
if(str) {
|
||||
if(str[0] != 'i' && str[0] != 'I') {
|
||||
speaker = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(speaker) {
|
||||
printf("Sending sound to internal speaker\n");
|
||||
output_channel |= AUDIO_OUT_SPEAKER;
|
||||
} else {
|
||||
printf("Sending sound to external jack\n");
|
||||
output_channel &= (~AUDIO_OUT_SPEAKER);
|
||||
output_channel |= AUDIO_OUT_HEADPHONE;
|
||||
}
|
||||
if(speaker) {
|
||||
printf("Sending sound to internal speaker\n");
|
||||
output_channel |= AUDIO_OUT_SPEAKER;
|
||||
} else {
|
||||
printf("Sending sound to external jack\n");
|
||||
output_channel &= (~AUDIO_OUT_SPEAKER);
|
||||
output_channel |= AUDIO_OUT_HEADPHONE;
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_OUTPUT, output_channel);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_OUTPUT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_OUTPUT, output_channel);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_OUTPUT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif /* HPUX */
|
||||
#endif /* HPUX */
|
||||
|
||||
#if defined(__linux__) || defined(OSS)
|
||||
void
|
||||
child_sound_init_linux()
|
||||
{
|
||||
int stereo;
|
||||
int sample_size;
|
||||
int rate;
|
||||
int fragment;
|
||||
int fmt;
|
||||
int ret;
|
||||
void child_sound_init_linux() {
|
||||
int stereo;
|
||||
int sample_size;
|
||||
int rate;
|
||||
int fragment;
|
||||
int fmt;
|
||||
int ret;
|
||||
|
||||
g_audio_socket = open("/dev/dsp", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/dsp failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
g_audio_socket = open("/dev/dsp", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/dsp failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fragment = 0x00200009;
|
||||
fragment = 0x00200009;
|
||||
#if 0
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFRAGMENT, &fragment);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SETFRAGEMNT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFRAGMENT, &fragment);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SETFRAGEMNT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
sample_size = 16;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SAMPLESIZE, &sample_size);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SAMPLESIZE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
sample_size = 16;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SAMPLESIZE, &sample_size);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SAMPLESIZE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if defined(GSPLUS_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
|
||||
fmt = AFMT_S16_LE;
|
||||
fmt = AFMT_S16_LE;
|
||||
#else
|
||||
fmt = AFMT_S16_BE;
|
||||
fmt = AFMT_S16_BE;
|
||||
#endif
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFMT, &fmt);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SETFMT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFMT, &fmt);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SETFMT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
stereo = 1;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_STEREO, &stereo);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_STEREO failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
stereo = 1;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_STEREO, &stereo);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_STEREO failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rate = g_audio_rate;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SPEED, &rate);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SPEED failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
if(ret > 0) {
|
||||
rate = ret; /* rate is returned value */
|
||||
}
|
||||
if(rate < 8000) {
|
||||
printf("Audio rate of %d which is < 8000!\n", rate);
|
||||
exit(1);
|
||||
}
|
||||
rate = g_audio_rate;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SPEED, &rate);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SPEED failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
if(ret > 0) {
|
||||
rate = ret; /* rate is returned value */
|
||||
}
|
||||
if(rate < 8000) {
|
||||
printf("Audio rate of %d which is < 8000!\n", rate);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_audio_rate = rate;
|
||||
g_audio_rate = rate;
|
||||
|
||||
printf("Sound initialized\n");
|
||||
printf("Sound initialized\n");
|
||||
}
|
||||
#endif
|
||||
|
|
2139
src/tfe/tfe.c
2139
src/tfe/tfe.c
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* tfearch.c - TFE ("The final ethernet") emulation,
|
||||
* tfearch.c - TFE ("The final ethernet") emulation,
|
||||
* architecture-dependant stuff
|
||||
*
|
||||
* Written by
|
||||
* Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>
|
||||
*
|
||||
*
|
||||
* This file is part of VICE, the Versatile Commodore Emulator.
|
||||
* See README for copyright notice.
|
||||
*
|
||||
|
@ -24,7 +24,7 @@
|
|||
* 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
@ -33,7 +33,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "../atbridge/pcap_delay.h"
|
||||
#include "tfesupp.h"
|
||||
#include "tfesupp.h"
|
||||
#include "../defc.h"
|
||||
#include "protos_tfe.h"
|
||||
|
||||
|
@ -60,36 +60,35 @@ static char TfePcapErrbuf[PCAP_ERRBUF_SIZE];
|
|||
#ifdef TFE_DEBUG_PKTDUMP
|
||||
|
||||
static
|
||||
void debug_output( const char *text, unsigned char *what, int count )
|
||||
{
|
||||
char buffer[256];
|
||||
char *p = buffer;
|
||||
char *pbuffer1 = what;
|
||||
int len1 = count;
|
||||
int i;
|
||||
void debug_output( const char *text, unsigned char *what, int count ) {
|
||||
char buffer[256];
|
||||
char *p = buffer;
|
||||
char *pbuffer1 = what;
|
||||
int len1 = count;
|
||||
int i;
|
||||
|
||||
sprintf(buffer, "\n%s: length = %u\n", text, len1);
|
||||
sprintf(buffer, "\n%s: length = %u\n", text, len1);
|
||||
OutputDebugString(buffer);
|
||||
do {
|
||||
p = buffer;
|
||||
for (i=0; (i<8) && len1>0; len1--, i++) {
|
||||
sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++);
|
||||
p += 3;
|
||||
}
|
||||
*(p-1) = '\n'; *p = 0;
|
||||
OutputDebugString(buffer);
|
||||
do {
|
||||
p = buffer;
|
||||
for (i=0; (i<8) && len1>0; len1--, i++) {
|
||||
sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++);
|
||||
p += 3;
|
||||
}
|
||||
*(p-1) = '\n'; *p = 0;
|
||||
OutputDebugString(buffer);
|
||||
} while (len1>0);
|
||||
} while (len1>0);
|
||||
}
|
||||
#endif // #ifdef TFE_DEBUG_PKTDUMP
|
||||
|
||||
|
||||
/*
|
||||
These functions let the UI enumerate the available interfaces.
|
||||
These functions let the UI enumerate the available interfaces.
|
||||
|
||||
First, TfeEnumAdapterOpen() is used to start enumeration.
|
||||
First, TfeEnumAdapterOpen() is used to start enumeration.
|
||||
|
||||
TfeEnumAdapter is then used to gather information for each adapter present
|
||||
on the system, where:
|
||||
TfeEnumAdapter is then used to gather information for each adapter present
|
||||
on the system, where:
|
||||
|
||||
ppname points to a pointer which will hold the name of the interface
|
||||
ppdescription points to a pointer which will hold the description of the interface
|
||||
|
@ -97,123 +96,119 @@ void debug_output( const char *text, unsigned char *what, int count )
|
|||
For each of these parameters, new memory is allocated, so it has to be
|
||||
freed with lib_free().
|
||||
|
||||
TfeEnumAdapterClose() must be used to stop processing.
|
||||
TfeEnumAdapterClose() must be used to stop processing.
|
||||
|
||||
Each function returns 1 on success, and 0 on failure.
|
||||
TfeEnumAdapter() only fails if there is no more adpater; in this case,
|
||||
*ppname and *ppdescription are not altered.
|
||||
*/
|
||||
int tfe_arch_enumadapter_open(void)
|
||||
{
|
||||
if (pcapdelay_findalldevs(&TfePcapAlldevs, TfePcapErrbuf) == -1)
|
||||
{
|
||||
Each function returns 1 on success, and 0 on failure.
|
||||
TfeEnumAdapter() only fails if there is no more adpater; in this case,
|
||||
* ppname and *ppdescription are not altered.
|
||||
*/
|
||||
int tfe_arch_enumadapter_open(void) {
|
||||
if (pcapdelay_findalldevs(&TfePcapAlldevs, TfePcapErrbuf) == -1)
|
||||
{
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen: pcap_findalldevs: '%s'", TfePcapErrbuf);
|
||||
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen: pcap_findalldevs: '%s'", TfePcapErrbuf);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!TfePcapAlldevs) {
|
||||
if (!TfePcapAlldevs) {
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - "
|
||||
"Do we have the necessary privilege rights?");
|
||||
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - "
|
||||
"Do we have the necessary privilege rights?");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TfePcapNextDev = TfePcapAlldevs;
|
||||
TfePcapNextDev = TfePcapAlldevs;
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tfe_arch_enumadapter(char **ppname, char **ppdescription)
|
||||
{
|
||||
if (!TfePcapNextDev || (TfePcapNextDev->name == NULL))
|
||||
return 0;
|
||||
int tfe_arch_enumadapter(char **ppname, char **ppdescription) {
|
||||
if (!TfePcapNextDev || (TfePcapNextDev->name == NULL))
|
||||
return 0;
|
||||
|
||||
*ppname = lib_stralloc(TfePcapNextDev->name);
|
||||
if (TfePcapNextDev->description)
|
||||
*ppdescription = lib_stralloc(TfePcapNextDev->description);
|
||||
else
|
||||
*ppdescription = lib_stralloc(TfePcapNextDev->name);
|
||||
TfePcapNextDev = TfePcapNextDev->next;
|
||||
*ppname = lib_stralloc(TfePcapNextDev->name);
|
||||
if (TfePcapNextDev->description)
|
||||
*ppdescription = lib_stralloc(TfePcapNextDev->description);
|
||||
else
|
||||
*ppdescription = lib_stralloc(TfePcapNextDev->name);
|
||||
TfePcapNextDev = TfePcapNextDev->next;
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tfe_arch_enumadapter_close(void)
|
||||
{
|
||||
if (TfePcapAlldevs) {
|
||||
pcapdelay_freealldevs(TfePcapAlldevs);
|
||||
TfePcapAlldevs = NULL;
|
||||
}
|
||||
return 1;
|
||||
int tfe_arch_enumadapter_close(void) {
|
||||
if (TfePcapAlldevs) {
|
||||
pcapdelay_freealldevs(TfePcapAlldevs);
|
||||
TfePcapAlldevs = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int TfePcapOpenAdapter(const char *interface_name)
|
||||
{
|
||||
pcap_if_t *TfePcapDevice = NULL;
|
||||
int TfePcapOpenAdapter(const char *interface_name) {
|
||||
pcap_if_t *TfePcapDevice = NULL;
|
||||
|
||||
if (!tfe_enumadapter_open()) {
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
/* look if we can find the specified adapter */
|
||||
char *pname;
|
||||
char *pdescription;
|
||||
int found = FALSE;
|
||||
if (!tfe_enumadapter_open()) {
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
/* look if we can find the specified adapter */
|
||||
char *pname;
|
||||
char *pdescription;
|
||||
int found = FALSE;
|
||||
|
||||
if (interface_name) {
|
||||
/* we have an interface name, try it */
|
||||
TfePcapDevice = TfePcapAlldevs;
|
||||
if (interface_name) {
|
||||
/* we have an interface name, try it */
|
||||
TfePcapDevice = TfePcapAlldevs;
|
||||
|
||||
while (tfe_enumadapter(&pname, &pdescription)) {
|
||||
if (strcmp(pname, interface_name)==0) {
|
||||
found = TRUE;
|
||||
}
|
||||
lib_free(pname);
|
||||
lib_free(pdescription);
|
||||
if (found) break;
|
||||
TfePcapDevice = TfePcapNextDev;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* just take the first adapter */
|
||||
TfePcapDevice = TfePcapAlldevs;
|
||||
while (tfe_enumadapter(&pname, &pdescription)) {
|
||||
if (strcmp(pname, interface_name)==0) {
|
||||
found = TRUE;
|
||||
}
|
||||
lib_free(pname);
|
||||
lib_free(pdescription);
|
||||
if (found) break;
|
||||
TfePcapDevice = TfePcapNextDev;
|
||||
}
|
||||
}
|
||||
|
||||
TfePcapFP = pcapdelay_open_live(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf);
|
||||
if ( TfePcapFP == NULL)
|
||||
{
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "ERROR opening adapter: '%s'", TfePcapErrbuf);
|
||||
#endif
|
||||
tfe_enumadapter_close();
|
||||
return FALSE;
|
||||
if (!found) {
|
||||
/* just take the first adapter */
|
||||
TfePcapDevice = TfePcapAlldevs;
|
||||
}
|
||||
}
|
||||
|
||||
if (pcapdelay_setnonblock(TfePcapFP, 1, TfePcapErrbuf)<0)
|
||||
{
|
||||
TfePcapFP = pcapdelay_open_live(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf);
|
||||
if ( TfePcapFP == NULL)
|
||||
{
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", TfePcapErrbuf);
|
||||
log_message(tfe_arch_log, "ERROR opening adapter: '%s'", TfePcapErrbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check the link layer. We support only Ethernet for simplicity. */
|
||||
if(pcapdelay_datalink(TfePcapFP) != DLT_EN10MB)
|
||||
{
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "ERROR: TFE works only on Ethernet networks.");
|
||||
#endif
|
||||
tfe_enumadapter_close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tfe_enumadapter_close();
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pcapdelay_setnonblock(TfePcapFP, 1, TfePcapErrbuf)<0)
|
||||
{
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", TfePcapErrbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check the link layer. We support only Ethernet for simplicity. */
|
||||
if(pcapdelay_datalink(TfePcapFP) != DLT_EN10MB)
|
||||
{
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message(tfe_arch_log, "ERROR: TFE works only on Ethernet networks.");
|
||||
#endif
|
||||
tfe_enumadapter_close();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tfe_enumadapter_close();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,50 +216,44 @@ int TfePcapOpenAdapter(const char *interface_name)
|
|||
/* the architecture-dependend functions */
|
||||
|
||||
|
||||
int tfe_arch_init(void)
|
||||
{
|
||||
//tfe_arch_log = log_open("TFEARCH");
|
||||
int tfe_arch_init(void) {
|
||||
//tfe_arch_log = log_open("TFEARCH");
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tfe_arch_pre_reset( void )
|
||||
{
|
||||
void tfe_arch_pre_reset( void ) {
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_pre_reset()." );
|
||||
log_message( tfe_arch_log, "tfe_arch_pre_reset()." );
|
||||
#endif
|
||||
}
|
||||
|
||||
void tfe_arch_post_reset( void )
|
||||
{
|
||||
void tfe_arch_post_reset( void ) {
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_post_reset()." );
|
||||
log_message( tfe_arch_log, "tfe_arch_post_reset()." );
|
||||
#endif
|
||||
}
|
||||
|
||||
int tfe_arch_activate(const char *interface_name)
|
||||
{
|
||||
int tfe_arch_activate(const char *interface_name) {
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_activate()." );
|
||||
log_message( tfe_arch_log, "tfe_arch_activate()." );
|
||||
#endif
|
||||
if (!TfePcapOpenAdapter(interface_name)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
if (!TfePcapOpenAdapter(interface_name)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tfe_arch_deactivate( void )
|
||||
{
|
||||
void tfe_arch_deactivate( void ) {
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_deactivate()." );
|
||||
log_message( tfe_arch_log, "tfe_arch_deactivate()." );
|
||||
#endif
|
||||
}
|
||||
|
||||
void tfe_arch_set_mac( const unsigned char mac[6] )
|
||||
{
|
||||
void tfe_arch_set_mac( const unsigned char mac[6] ) {
|
||||
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
|
||||
log_message( tfe_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
|
||||
log_message( tfe_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -275,49 +264,46 @@ void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */
|
|||
int bCorrect, /* accept correct frames */
|
||||
int bPromiscuous, /* promiscuous mode */
|
||||
int bIAHash /* accept if IA passes the hash filter */
|
||||
)
|
||||
{
|
||||
) {
|
||||
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
|
||||
log_message( tfe_arch_log, "tfe_arch_recv_ctl() called with the following parameters:" );
|
||||
log_message( tfe_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "tfe_arch_recv_ctl() called with the following parameters:" );
|
||||
log_message( tfe_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver )
|
||||
{
|
||||
void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver ) {
|
||||
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
|
||||
log_message( tfe_arch_log, "tfe_arch_line_ctl() called with the following parameters:" );
|
||||
log_message( tfe_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "tfe_arch_line_ctl() called with the following parameters:" );
|
||||
log_message( tfe_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" );
|
||||
log_message( tfe_arch_log, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
typedef struct TFE_PCAP_INTERNAL_tag {
|
||||
|
||||
unsigned int len;
|
||||
unsigned char *buffer;
|
||||
unsigned int len;
|
||||
unsigned char *buffer;
|
||||
|
||||
} TFE_PCAP_INTERNAL;
|
||||
|
||||
/* Callback function invoked by libpcap for every incoming packet */
|
||||
static
|
||||
void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data)
|
||||
{
|
||||
TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL*)param;
|
||||
void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data) {
|
||||
TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL*)param;
|
||||
|
||||
/* determine the count of bytes which has been returned,
|
||||
* but make sure not to overrun the buffer
|
||||
*/
|
||||
if (header->caplen < pinternal->len)
|
||||
pinternal->len = header->caplen;
|
||||
/* determine the count of bytes which has been returned,
|
||||
* but make sure not to overrun the buffer
|
||||
*/
|
||||
if (header->caplen < pinternal->len)
|
||||
pinternal->len = header->caplen;
|
||||
|
||||
memcpy(pinternal->buffer, pkt_data, pinternal->len);
|
||||
memcpy(pinternal->buffer, pkt_data, pinternal->len);
|
||||
}
|
||||
|
||||
/* the following function receives a frame.
|
||||
|
@ -325,27 +311,26 @@ void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header
|
|||
If there's none, it returns a -1.
|
||||
If there is one, it returns the length of the frame in bytes.
|
||||
|
||||
It copies the frame to *buffer and returns the number of copied
|
||||
It copies the frame to *buffer and returns the number of copied
|
||||
bytes as return value.
|
||||
|
||||
At most 'len' bytes are copied.
|
||||
*/
|
||||
static
|
||||
int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal)
|
||||
{
|
||||
int ret = -1;
|
||||
*/
|
||||
static
|
||||
int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) {
|
||||
int ret = -1;
|
||||
|
||||
/* check if there is something to receive */
|
||||
if (pcapdelay_dispatch(TfePcapFP, 1, (pcap_handler)TfePcapPacketHandler, (unsigned char*)pinternal)!=0) {
|
||||
/* Something has been received */
|
||||
ret = pinternal->len;
|
||||
}
|
||||
/* check if there is something to receive */
|
||||
if (pcapdelay_dispatch(TfePcapFP, 1, (pcap_handler)TfePcapPacketHandler, (unsigned char*)pinternal)!=0) {
|
||||
/* Something has been received */
|
||||
ret = pinternal->len;
|
||||
}
|
||||
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_receive_frame() called, returns %d.", ret );
|
||||
log_message( tfe_arch_log, "tfe_arch_receive_frame() called, returns %d.", ret );
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */
|
||||
|
@ -354,105 +339,103 @@ void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in trans
|
|||
int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
|
||||
int txlength, /* Frame length */
|
||||
unsigned char *txframe /* Pointer to the frame to be transmitted */
|
||||
)
|
||||
{
|
||||
) {
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_transmit() called, with: "
|
||||
"force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
|
||||
force ? "TRUE" : "FALSE",
|
||||
onecoll ? "TRUE" : "FALSE",
|
||||
inhibit_crc ? "TRUE" : "FALSE",
|
||||
tx_pad_dis ? "TRUE" : "FALSE",
|
||||
txlength
|
||||
);
|
||||
log_message( tfe_arch_log, "tfe_arch_transmit() called, with: "
|
||||
"force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
|
||||
force ? "TRUE" : "FALSE",
|
||||
onecoll ? "TRUE" : "FALSE",
|
||||
inhibit_crc ? "TRUE" : "FALSE",
|
||||
tx_pad_dis ? "TRUE" : "FALSE",
|
||||
txlength
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef TFE_DEBUG_PKTDUMP
|
||||
debug_output( "Transmit frame: ", txframe, txlength);
|
||||
debug_output( "Transmit frame: ", txframe, txlength);
|
||||
#endif // #ifdef TFE_DEBUG_PKTDUMP
|
||||
|
||||
if (pcapdelay_sendpacket(TfePcapFP, txframe, txlength) == -1) {
|
||||
//log_message(tfe_arch_log, "WARNING! Could not send packet!");
|
||||
}
|
||||
if (pcapdelay_sendpacket(TfePcapFP, txframe, txlength) == -1) {
|
||||
//log_message(tfe_arch_log, "WARNING! Could not send packet!");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
tfe_arch_receive()
|
||||
tfe_arch_receive()
|
||||
|
||||
This function checks if there was a frame received.
|
||||
If so, it returns 1, else 0.
|
||||
This function checks if there was a frame received.
|
||||
If so, it returns 1, else 0.
|
||||
|
||||
If there was no frame, none of the parameters is changed!
|
||||
If there was no frame, none of the parameters is changed!
|
||||
|
||||
If there was a frame, the following actions are done:
|
||||
If there was a frame, the following actions are done:
|
||||
|
||||
- at maximum *plen byte are transferred into the buffer given by pbuffer
|
||||
- *plen gets the length of the received frame, EVEN if this is more
|
||||
- at maximum *plen byte are transferred into the buffer given by pbuffer
|
||||
- *plen gets the length of the received frame, EVEN if this is more
|
||||
than has been copied to pbuffer!
|
||||
- if the dest. address was accepted by the hash filter, *phashed is set, else
|
||||
- if the dest. address was accepted by the hash filter, *phashed is set, else
|
||||
cleared.
|
||||
- if the dest. address was accepted by the hash filter, *phash_index is
|
||||
- if the dest. address was accepted by the hash filter, *phash_index is
|
||||
set to the number of the rule leading to the acceptance
|
||||
- if the receive was ok (good CRC and valid length), *prx_ok is set,
|
||||
- if the receive was ok (good CRC and valid length), *prx_ok is set,
|
||||
else cleared.
|
||||
- if the dest. address was accepted because it's exactly our MAC address
|
||||
- if the dest. address was accepted because it's exactly our MAC address
|
||||
(set by tfe_arch_set_mac()), *pcorrect_mac is set, else cleared.
|
||||
- if the dest. address was accepted since it was a broadcast address,
|
||||
*pbroadcast is set, else cleared.
|
||||
- if the received frame had a crc error, *pcrc_error is set, else cleared
|
||||
*/
|
||||
int tfe_arch_receive(unsigned char *pbuffer , /* where to store a frame */
|
||||
int *plen, /* IN: maximum length of frame to copy;
|
||||
OUT: length of received frame
|
||||
- if the dest. address was accepted since it was a broadcast address,
|
||||
* pbroadcast is set, else cleared.
|
||||
- if the received frame had a crc error, *pcrc_error is set, else cleared
|
||||
*/
|
||||
int tfe_arch_receive(unsigned char *pbuffer, /* where to store a frame */
|
||||
int *plen, /* IN: maximum length of frame to copy;
|
||||
OUT: length of received frame
|
||||
OUT can be bigger than IN if received frame was
|
||||
longer than supplied buffer */
|
||||
int *phashed, /* set if the dest. address is accepted by the hash filter */
|
||||
int *phash_index, /* hash table index if hashed == TRUE */
|
||||
int *phash_index, /* hash table index if hashed == TRUE */
|
||||
int *prx_ok, /* set if good CRC and valid length */
|
||||
int *pcorrect_mac, /* set if dest. address is exactly our IA */
|
||||
int *pbroadcast, /* set if dest. address is a broadcast address */
|
||||
int *pcrc_error /* set if received frame had a CRC error */
|
||||
)
|
||||
{
|
||||
int len;
|
||||
) {
|
||||
int len;
|
||||
|
||||
TFE_PCAP_INTERNAL internal = { *plen, pbuffer };
|
||||
TFE_PCAP_INTERNAL internal = { *plen, pbuffer };
|
||||
|
||||
|
||||
#ifdef TFE_DEBUG_ARCH
|
||||
log_message( tfe_arch_log, "tfe_arch_receive() called, with *plen=%u.", *plen );
|
||||
log_message( tfe_arch_log, "tfe_arch_receive() called, with *plen=%u.", *plen );
|
||||
#endif
|
||||
|
||||
assert((*plen&1)==0);
|
||||
assert((*plen&1)==0);
|
||||
|
||||
len = tfe_arch_receive_frame(&internal);
|
||||
len = tfe_arch_receive_frame(&internal);
|
||||
|
||||
if (len!=-1) {
|
||||
if (len!=-1) {
|
||||
|
||||
#ifdef TFE_DEBUG_PKTDUMP
|
||||
debug_output( "Received frame: ", internal.buffer, internal.len );
|
||||
debug_output( "Received frame: ", internal.buffer, internal.len );
|
||||
#endif // #ifdef TFE_DEBUG_PKTDUMP
|
||||
|
||||
if (len&1)
|
||||
++len;
|
||||
if (len&1)
|
||||
++len;
|
||||
|
||||
*plen = len;
|
||||
*plen = len;
|
||||
|
||||
/* we don't decide if this frame fits the needs;
|
||||
* by setting all zero, we let tfe.c do the work
|
||||
* for us
|
||||
*/
|
||||
*phashed =
|
||||
*phash_index =
|
||||
*pbroadcast =
|
||||
*pcorrect_mac =
|
||||
*pcrc_error = 0;
|
||||
/* we don't decide if this frame fits the needs;
|
||||
* by setting all zero, we let tfe.c do the work
|
||||
* for us
|
||||
*/
|
||||
*phashed =
|
||||
*phash_index =
|
||||
*pbroadcast =
|
||||
*pcorrect_mac =
|
||||
*pcrc_error = 0;
|
||||
|
||||
/* this frame has been received correctly */
|
||||
*prx_ok = 1;
|
||||
/* this frame has been received correctly */
|
||||
*prx_ok = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -61,123 +61,117 @@
|
|||
static unsigned long crc32_table[256];
|
||||
static int crc32_is_initialized = 0;
|
||||
|
||||
void lib_free(void *ptr)
|
||||
{
|
||||
void lib_free(void *ptr) {
|
||||
#ifdef LIB_DEBUG
|
||||
lib_debug_free(ptr, 1, 1);
|
||||
lib_debug_free(ptr, 1, 1);
|
||||
#endif
|
||||
|
||||
#ifdef LIB_DEBUG
|
||||
lib_debug_libc_free(ptr);
|
||||
lib_debug_libc_free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *lib_malloc(size_t size)
|
||||
{
|
||||
void *lib_malloc(size_t size) {
|
||||
#ifdef LIB_DEBUG
|
||||
void *ptr = lib_debug_libc_malloc(size);
|
||||
void *ptr = lib_debug_libc_malloc(size);
|
||||
#else
|
||||
void *ptr = malloc(size);
|
||||
void *ptr = malloc(size);
|
||||
#endif
|
||||
|
||||
if (ptr == NULL && size > 0)
|
||||
exit(-1);
|
||||
if (ptr == NULL && size > 0)
|
||||
exit(-1);
|
||||
#ifdef LIB_DEBUG
|
||||
lib_debug_alloc(ptr, size, 3);
|
||||
lib_debug_alloc(ptr, size, 3);
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Malloc enough space for `str', copy `str' into it and return its
|
||||
address. */
|
||||
char *lib_stralloc(const char *str)
|
||||
{
|
||||
size_t size;
|
||||
char *ptr;
|
||||
char *lib_stralloc(const char *str) {
|
||||
size_t size;
|
||||
char *ptr;
|
||||
|
||||
if (str == NULL)
|
||||
exit(-1);
|
||||
if (str == NULL)
|
||||
exit(-1);
|
||||
|
||||
size = strlen(str) + 1;
|
||||
ptr = (char *)lib_malloc(size);
|
||||
size = strlen(str) + 1;
|
||||
ptr = (char *)lib_malloc(size);
|
||||
|
||||
memcpy(ptr, str, size);
|
||||
return ptr;
|
||||
memcpy(ptr, str, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Like realloc, but abort if not enough memory is available. */
|
||||
void *lib_realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *lib_realloc(void *ptr, size_t size) {
|
||||
#ifdef LIB_DEBUG
|
||||
void *new_ptr = lib_debug_libc_realloc(ptr, size);
|
||||
void *new_ptr = lib_debug_libc_realloc(ptr, size);
|
||||
#else
|
||||
void *new_ptr = realloc(ptr, size);
|
||||
void *new_ptr = realloc(ptr, size);
|
||||
#endif
|
||||
|
||||
if (new_ptr == NULL)
|
||||
exit(-1);
|
||||
if (new_ptr == NULL)
|
||||
exit(-1);
|
||||
#ifdef LIB_DEBUG
|
||||
lib_debug_free(ptr, 1, 0);
|
||||
lib_debug_alloc(new_ptr, size, 1);
|
||||
lib_debug_free(ptr, 1, 0);
|
||||
lib_debug_alloc(new_ptr, size, 1);
|
||||
#endif
|
||||
|
||||
return new_ptr;
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
// Util Stuff
|
||||
|
||||
/* Set a new value to the dynamically allocated string *str.
|
||||
Returns `-1' if nothing has to be done. */
|
||||
int util_string_set(char **str, const char *new_value)
|
||||
{
|
||||
if (*str == NULL) {
|
||||
if (new_value != NULL)
|
||||
*str = lib_stralloc(new_value);
|
||||
int util_string_set(char **str, const char *new_value) {
|
||||
if (*str == NULL) {
|
||||
if (new_value != NULL)
|
||||
*str = lib_stralloc(new_value);
|
||||
} else {
|
||||
if (new_value == NULL) {
|
||||
lib_free(*str);
|
||||
*str = NULL;
|
||||
} else {
|
||||
if (new_value == NULL) {
|
||||
lib_free(*str);
|
||||
*str = NULL;
|
||||
} else {
|
||||
/* Skip copy if src and dest are already the same. */
|
||||
if (strcmp(*str, new_value) == 0)
|
||||
return -1;
|
||||
/* Skip copy if src and dest are already the same. */
|
||||
if (strcmp(*str, new_value) == 0)
|
||||
return -1;
|
||||
|
||||
*str = (char *)lib_realloc(*str, strlen(new_value) + 1);
|
||||
strcpy(*str, new_value);
|
||||
}
|
||||
*str = (char *)lib_realloc(*str, strlen(new_value) + 1);
|
||||
strcpy(*str, new_value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// crc32 Stuff
|
||||
|
||||
unsigned long crc32_buf(const char *buffer, unsigned int len)
|
||||
{
|
||||
int i, j;
|
||||
unsigned long crc, c;
|
||||
const char *p;
|
||||
unsigned long crc32_buf(const char *buffer, unsigned int len) {
|
||||
int i, j;
|
||||
unsigned long crc, c;
|
||||
const char *p;
|
||||
|
||||
if (!crc32_is_initialized) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = (unsigned long) i;
|
||||
for (j = 0; j < 8; j++)
|
||||
c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1;
|
||||
crc32_table[i] = c;
|
||||
}
|
||||
crc32_is_initialized = 1;
|
||||
if (!crc32_is_initialized) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = (unsigned long) i;
|
||||
for (j = 0; j < 8; j++)
|
||||
c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1;
|
||||
crc32_table[i] = c;
|
||||
}
|
||||
crc32_is_initialized = 1;
|
||||
}
|
||||
|
||||
crc = 0xffffffff;
|
||||
for (p = buffer; len > 0; ++p, --len)
|
||||
crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff];
|
||||
crc = 0xffffffff;
|
||||
for (p = buffer; len > 0; ++p, --len)
|
||||
crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff];
|
||||
|
||||
return ~crc;
|
||||
return ~crc;
|
||||
}
|
||||
|
|
1525
src/to_pro.c
1525
src/to_pro.c
File diff suppressed because it is too large
Load Diff
5758
src/video.c
5758
src/video.c
File diff suppressed because it is too large
Load Diff
4112
src/win32_host_fst.c
4112
src/win32_host_fst.c
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#include "defc.h"
|
||||
#include "sound.h"
|
||||
|
@ -18,215 +18,201 @@ extern int g_audio_rate;
|
|||
unsigned int __stdcall child_sound_loop_win32(void *param);
|
||||
void check_wave_error(int res, char *str);
|
||||
|
||||
#define NUM_WAVE_HEADERS 8
|
||||
#define NUM_WAVE_HEADERS 8
|
||||
|
||||
HWAVEOUT g_wave_handle = NULL; // OG Default value must be set
|
||||
HWAVEOUT g_wave_handle = NULL; // OG Default value must be set
|
||||
WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
|
||||
|
||||
extern int g_audio_enable;
|
||||
extern word32 *g_sound_shm_addr;
|
||||
extern int g_preferred_rate;
|
||||
|
||||
int g_win32snd_buflen = 0x1000;
|
||||
int g_win32snd_buflen = 0x1000;
|
||||
|
||||
void
|
||||
win32snd_init(word32 *shmaddr)
|
||||
{
|
||||
printf("win32snd_init\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
void win32snd_init(word32 *shmaddr) {
|
||||
printf("win32snd_init\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// OG Added global to free the dedicated win32 sound memory
|
||||
byte *bptr = NULL;
|
||||
byte *bptr = NULL;
|
||||
|
||||
// OG shut win32 sound resources
|
||||
void
|
||||
win32snd_shutdown()
|
||||
{
|
||||
void win32snd_shutdown() {
|
||||
|
||||
if (g_wave_handle)
|
||||
{
|
||||
MMRESULT res = waveOutReset(g_wave_handle);
|
||||
if (res!=MMSYSERR_NOERROR )
|
||||
printf("waveOutReset Failed");
|
||||
if (g_wave_handle)
|
||||
{
|
||||
MMRESULT res = waveOutReset(g_wave_handle);
|
||||
if (res!=MMSYSERR_NOERROR )
|
||||
printf("waveOutReset Failed");
|
||||
|
||||
res = waveOutClose(g_wave_handle);
|
||||
if (res!=MMSYSERR_NOERROR )
|
||||
printf("waveOutClose Failed");
|
||||
g_wave_handle=NULL;
|
||||
}
|
||||
// OG Free dedicated sound memory
|
||||
if (bptr)
|
||||
{
|
||||
free(bptr);
|
||||
bptr = NULL;
|
||||
}
|
||||
res = waveOutClose(g_wave_handle);
|
||||
if (res!=MMSYSERR_NOERROR )
|
||||
printf("waveOutClose Failed");
|
||||
g_wave_handle=NULL;
|
||||
}
|
||||
// OG Free dedicated sound memory
|
||||
if (bptr)
|
||||
{
|
||||
free(bptr);
|
||||
bptr = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CALLBACK
|
||||
handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
|
||||
DWORD_PTR dwParam2)
|
||||
{
|
||||
LPWAVEHDR lpwavehdr;
|
||||
void CALLBACK handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
|
||||
DWORD_PTR dwParam2) {
|
||||
LPWAVEHDR lpwavehdr;
|
||||
|
||||
/* Only service "buffer done playing messages */
|
||||
if(uMsg == WOM_DONE) {
|
||||
lpwavehdr = (LPWAVEHDR)dwParam1;
|
||||
if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) {
|
||||
lpwavehdr->dwUser = FALSE;
|
||||
}
|
||||
}
|
||||
/* Only service "buffer done playing messages */
|
||||
if(uMsg == WOM_DONE) {
|
||||
lpwavehdr = (LPWAVEHDR)dwParam1;
|
||||
if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) {
|
||||
lpwavehdr->dwUser = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
void
|
||||
check_wave_error(int res, char *str)
|
||||
{
|
||||
TCHAR buf[256];
|
||||
void check_wave_error(int res, char *str) {
|
||||
TCHAR buf[256];
|
||||
|
||||
if(res == MMSYSERR_NOERROR) {
|
||||
return;
|
||||
}
|
||||
if(res == MMSYSERR_NOERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
waveOutGetErrorText(res, &buf[0], sizeof(buf));
|
||||
printf("%s: %s\n", str, buf);
|
||||
exit(1);
|
||||
waveOutGetErrorText(res, &buf[0], sizeof(buf));
|
||||
printf("%s: %s\n", str, buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
child_sound_init_win32()
|
||||
{
|
||||
WAVEFORMATEX wavefmt;
|
||||
WAVEOUTCAPS caps;
|
||||
void child_sound_init_win32() {
|
||||
WAVEFORMATEX wavefmt;
|
||||
WAVEOUTCAPS caps;
|
||||
|
||||
// OG Moved as global variable (to rename)
|
||||
// byte *bptr;
|
||||
int bits_per_sample, channels, block_align;
|
||||
int blen;
|
||||
int res;
|
||||
int i;
|
||||
int bits_per_sample, channels, block_align;
|
||||
int blen;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
memset(&wavefmt, 0, sizeof(WAVEFORMATEX));
|
||||
memset(&wavefmt, 0, sizeof(WAVEFORMATEX));
|
||||
|
||||
wavefmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wavefmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
#ifndef UNDER_CE
|
||||
bits_per_sample = 16;
|
||||
wavefmt.nSamplesPerSec = g_audio_rate;
|
||||
bits_per_sample = 16;
|
||||
wavefmt.nSamplesPerSec = g_audio_rate;
|
||||
#else
|
||||
bits_per_sample = 16;
|
||||
wavefmt.nSamplesPerSec = 12000;
|
||||
bits_per_sample = 16;
|
||||
wavefmt.nSamplesPerSec = 12000;
|
||||
#endif
|
||||
|
||||
channels = 2;
|
||||
wavefmt.wBitsPerSample = bits_per_sample;
|
||||
wavefmt.nChannels = channels;
|
||||
block_align = channels * (bits_per_sample / 8);
|
||||
wavefmt.nBlockAlign = block_align;
|
||||
wavefmt.nAvgBytesPerSec = block_align * g_audio_rate;
|
||||
channels = 2;
|
||||
wavefmt.wBitsPerSample = bits_per_sample;
|
||||
wavefmt.nChannels = channels;
|
||||
block_align = channels * (bits_per_sample / 8);
|
||||
wavefmt.nBlockAlign = block_align;
|
||||
wavefmt.nAvgBytesPerSec = block_align * g_audio_rate;
|
||||
|
||||
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0,
|
||||
WAVE_FORMAT_QUERY);
|
||||
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0,
|
||||
WAVE_FORMAT_QUERY);
|
||||
|
||||
if(res != MMSYSERR_NOERROR) {
|
||||
printf("Cannot open audio device\n");
|
||||
g_audio_enable = 0;
|
||||
return;
|
||||
}
|
||||
if(res != MMSYSERR_NOERROR) {
|
||||
printf("Cannot open audio device\n");
|
||||
g_audio_enable = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt,
|
||||
(DWORD_PTR)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
|
||||
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt,
|
||||
(DWORD_PTR)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
|
||||
|
||||
if(res != MMSYSERR_NOERROR) {
|
||||
printf("Cannot register audio\n");
|
||||
g_audio_enable = 0;
|
||||
return;
|
||||
}
|
||||
if(res != MMSYSERR_NOERROR) {
|
||||
printf("Cannot register audio\n");
|
||||
g_audio_enable = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
g_audio_rate = wavefmt.nSamplesPerSec;
|
||||
g_audio_rate = wavefmt.nSamplesPerSec;
|
||||
|
||||
blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS;
|
||||
g_win32snd_buflen = blen;
|
||||
bptr = (byte*)malloc(blen * NUM_WAVE_HEADERS); // OG Added cast
|
||||
if(bptr == NULL) {
|
||||
printf("Unabled to allocate sound buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS;
|
||||
g_win32snd_buflen = blen;
|
||||
bptr = (byte*)malloc(blen * NUM_WAVE_HEADERS); // OG Added cast
|
||||
if(bptr == NULL) {
|
||||
printf("Unabled to allocate sound buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
|
||||
memset(&g_wavehdr[i], 0, sizeof(WAVEHDR));
|
||||
g_wavehdr[i].dwUser = FALSE;
|
||||
g_wavehdr[i].lpData = (LPSTR)&(bptr[i*blen]); // OG Added cast
|
||||
g_wavehdr[i].dwBufferLength = blen;
|
||||
g_wavehdr[i].dwFlags = 0;
|
||||
g_wavehdr[i].dwLoops = 0;
|
||||
res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i],
|
||||
sizeof(WAVEHDR));
|
||||
check_wave_error(res, "waveOutPrepareHeader");
|
||||
}
|
||||
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
|
||||
memset(&g_wavehdr[i], 0, sizeof(WAVEHDR));
|
||||
g_wavehdr[i].dwUser = FALSE;
|
||||
g_wavehdr[i].lpData = (LPSTR)&(bptr[i*blen]); // OG Added cast
|
||||
g_wavehdr[i].dwBufferLength = blen;
|
||||
g_wavehdr[i].dwFlags = 0;
|
||||
g_wavehdr[i].dwLoops = 0;
|
||||
res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i],
|
||||
sizeof(WAVEHDR));
|
||||
check_wave_error(res, "waveOutPrepareHeader");
|
||||
}
|
||||
|
||||
res = waveOutGetDevCaps((UINT_PTR)g_wave_handle, &caps, sizeof(caps));
|
||||
check_wave_error(res, "waveOutGetDevCaps");
|
||||
printf("Using %s\n", caps.szPname);
|
||||
printf(" Bits per Sample = %d. Channels = %d\n",
|
||||
wavefmt.wBitsPerSample, wavefmt.nChannels);
|
||||
printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n",
|
||||
(int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec);
|
||||
res = waveOutGetDevCaps((UINT_PTR)g_wave_handle, &caps, sizeof(caps));
|
||||
check_wave_error(res, "waveOutGetDevCaps");
|
||||
printf("Using %s\n", caps.szPname);
|
||||
printf(" Bits per Sample = %d. Channels = %d\n",
|
||||
wavefmt.wBitsPerSample, wavefmt.nChannels);
|
||||
printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n",
|
||||
(int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec);
|
||||
|
||||
set_audio_rate(g_audio_rate);
|
||||
set_audio_rate(g_audio_rate);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
win32_send_audio2(byte *ptr, int size)
|
||||
{
|
||||
int found;
|
||||
int res;
|
||||
int i;
|
||||
void win32_send_audio2(byte *ptr, int size) {
|
||||
int found;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
found = 0;
|
||||
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
|
||||
if(g_wavehdr[i].dwUser == FALSE) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
found = 0;
|
||||
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
|
||||
if(g_wavehdr[i].dwUser == FALSE) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
/* all audio buffers busy, just get out */
|
||||
return;
|
||||
}
|
||||
if(!found) {
|
||||
/* all audio buffers busy, just get out */
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(g_wavehdr[i].lpData, ptr, size);
|
||||
g_wavehdr[i].dwBufferLength = size;
|
||||
g_wavehdr[i].dwUser = TRUE;
|
||||
memcpy(g_wavehdr[i].lpData, ptr, size);
|
||||
g_wavehdr[i].dwBufferLength = size;
|
||||
g_wavehdr[i].dwUser = TRUE;
|
||||
|
||||
res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr));
|
||||
check_wave_error(res, "waveOutWrite");
|
||||
res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr));
|
||||
check_wave_error(res, "waveOutWrite");
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
win32_send_audio(byte *ptr, int in_size)
|
||||
{
|
||||
int size;
|
||||
int tmpsize;
|
||||
int win32_send_audio(byte *ptr, int in_size) {
|
||||
int size;
|
||||
int tmpsize;
|
||||
|
||||
size = in_size;
|
||||
while(size > 0) {
|
||||
tmpsize = size;
|
||||
if(size > g_win32snd_buflen) {
|
||||
tmpsize = g_win32snd_buflen;
|
||||
}
|
||||
win32_send_audio2(ptr, tmpsize);
|
||||
ptr += tmpsize;
|
||||
size = size - tmpsize;
|
||||
}
|
||||
size = in_size;
|
||||
while(size > 0) {
|
||||
tmpsize = size;
|
||||
if(size > g_win32snd_buflen) {
|
||||
tmpsize = g_win32snd_buflen;
|
||||
}
|
||||
win32_send_audio2(ptr, tmpsize);
|
||||
ptr += tmpsize;
|
||||
size = size - tmpsize;
|
||||
}
|
||||
|
||||
return in_size;
|
||||
return in_size;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
GSPLUS - Advanced Apple IIGS Emulator Environment
|
||||
Based on the KEGS emulator written by Kent Dickey
|
||||
See COPYRIGHT.txt for Copyright information
|
||||
See LICENSE.txt for license (GPL v2)
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */
|
||||
#define STRICT /* Tell Windows we want compile type checks */
|
||||
#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */
|
||||
#define STRICT /* Tell Windows we want compile type checks */
|
||||
|
||||
#include <windows.h>
|
||||
#include <Shlwapi.h>
|
||||
|
@ -21,206 +21,188 @@ extern void gsportshut();
|
|||
extern HWND g_hwnd_main;
|
||||
|
||||
extern char *g_status_ptrs[MAX_STATUS_LINES];
|
||||
extern int g_win_status_debug;
|
||||
extern int g_win_status_debug_request;
|
||||
extern int g_win_fullscreen_state;
|
||||
extern int g_win_status_debug;
|
||||
extern int g_win_status_debug_request;
|
||||
extern int g_win_fullscreen_state;
|
||||
|
||||
int
|
||||
win_nonblock_read_stdin(int fd, char *bufptr, int len)
|
||||
{
|
||||
DWORD charsRead = 0;
|
||||
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), bufptr, len, &charsRead, NULL);
|
||||
|
||||
if (charsRead == 0)
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD charsWritten = 0;
|
||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), bufptr, charsRead, &charsWritten, NULL);
|
||||
return charsRead;
|
||||
}
|
||||
int win_nonblock_read_stdin(int fd, char *bufptr, int len) {
|
||||
DWORD charsRead = 0;
|
||||
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), bufptr, len, &charsRead, NULL);
|
||||
|
||||
if (charsRead == 0)
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD charsWritten = 0;
|
||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), bufptr, charsRead, &charsWritten, NULL);
|
||||
return charsRead;
|
||||
}
|
||||
}
|
||||
|
||||
void get_cwd(LPTSTR buffer, int size)
|
||||
{
|
||||
HMODULE hSelf;
|
||||
hSelf = GetModuleHandle(NULL);
|
||||
GetModuleFileName(hSelf,buffer,size);
|
||||
PathRemoveFileSpec(buffer);
|
||||
//printf("Local directory: [%s]\n",buffer);
|
||||
void get_cwd(LPTSTR buffer, int size) {
|
||||
HMODULE hSelf;
|
||||
hSelf = GetModuleHandle(NULL);
|
||||
GetModuleFileName(hSelf,buffer,size);
|
||||
PathRemoveFileSpec(buffer);
|
||||
//printf("Local directory: [%s]\n",buffer);
|
||||
}
|
||||
|
||||
void
|
||||
x_dialog_create_gsport_conf(const char *str)
|
||||
{
|
||||
// Just write the config file already...
|
||||
config_write_config_gsplus_file();
|
||||
void x_dialog_create_gsport_conf(const char *str) {
|
||||
// Just write the config file already...
|
||||
config_write_config_gsplus_file();
|
||||
}
|
||||
|
||||
int
|
||||
x_show_alert(int is_fatal, const char *str)
|
||||
{
|
||||
return 0;
|
||||
int x_show_alert(int is_fatal, const char *str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_default_window_size(LPSIZE size)
|
||||
{
|
||||
// Calculate the window client dimensions.
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.bottom = X_A2_WINDOW_HEIGHT;
|
||||
if (g_win_status_debug)
|
||||
rect.bottom += (MAX_STATUS_LINES * 16);
|
||||
rect.right = X_A2_WINDOW_WIDTH;
|
||||
void get_default_window_size(LPSIZE size) {
|
||||
// Calculate the window client dimensions.
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.bottom = X_A2_WINDOW_HEIGHT;
|
||||
if (g_win_status_debug)
|
||||
rect.bottom += (MAX_STATUS_LINES * 16);
|
||||
rect.right = X_A2_WINDOW_WIDTH;
|
||||
|
||||
// Calculate the window rectangle, which is the client area plus non-client area (e.g. frame and caption).
|
||||
AdjustWindowRect(&rect, WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
|
||||
|
||||
// Return the window size.
|
||||
size->cx = rect.right - rect.left;
|
||||
size->cy = rect.bottom - rect.top;
|
||||
// Calculate the window rectangle, which is the client area plus non-client area (e.g. frame and caption).
|
||||
AdjustWindowRect(&rect, WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
|
||||
|
||||
// Return the window size.
|
||||
size->cx = rect.right - rect.left;
|
||||
size->cy = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
void x_toggle_status_lines()
|
||||
{
|
||||
SIZE size;
|
||||
void x_toggle_status_lines() {
|
||||
SIZE size;
|
||||
|
||||
if (!g_win_fullscreen_state)
|
||||
{
|
||||
g_win_status_debug = !g_win_status_debug;
|
||||
g_win_status_debug_request = g_win_status_debug;
|
||||
if (!g_win_fullscreen_state)
|
||||
{
|
||||
g_win_status_debug = !g_win_status_debug;
|
||||
g_win_status_debug_request = g_win_status_debug;
|
||||
|
||||
get_default_window_size(&size);
|
||||
SetWindowPos(g_hwnd_main, NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOZORDER);
|
||||
x_redraw_status_lines();
|
||||
}
|
||||
get_default_window_size(&size);
|
||||
SetWindowPos(g_hwnd_main, NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOZORDER);
|
||||
x_redraw_status_lines();
|
||||
}
|
||||
}
|
||||
|
||||
void x_show_console(int show)
|
||||
{
|
||||
HWND hWnd = GetConsoleWindow();
|
||||
if (hWnd)
|
||||
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
|
||||
void x_show_console(int show) {
|
||||
HWND hWnd = GetConsoleWindow();
|
||||
if (hWnd)
|
||||
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
|
||||
|
||||
if (g_hwnd_main)
|
||||
SetFocus(g_hwnd_main);
|
||||
if (g_hwnd_main)
|
||||
SetFocus(g_hwnd_main);
|
||||
}
|
||||
|
||||
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
return main(0,0);
|
||||
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
|
||||
return main(0,0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
// Hide the console initially to reduce window flashing. We'll show the console later if needed.
|
||||
x_show_console(0);
|
||||
int main(int argc, char **argv) {
|
||||
// Hide the console initially to reduce window flashing. We'll show the console later if needed.
|
||||
x_show_console(0);
|
||||
|
||||
// Register the window class.
|
||||
WNDCLASS wndclass;
|
||||
SIZE size;
|
||||
RECT rect;
|
||||
// Register the window class.
|
||||
WNDCLASS wndclass;
|
||||
SIZE size;
|
||||
RECT rect;
|
||||
|
||||
wndclass.style = 0;
|
||||
wndclass.lpfnWndProc = (WNDPROC)win_event_handler;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = GetModuleHandle(NULL);
|
||||
wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDC_GSPORT32));
|
||||
wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
|
||||
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = "gsport";
|
||||
wndclass.style = 0;
|
||||
wndclass.lpfnWndProc = (WNDPROC)win_event_handler;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = GetModuleHandle(NULL);
|
||||
wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDC_GSPORT32));
|
||||
wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
|
||||
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = "gsport";
|
||||
|
||||
if(!RegisterClass(&wndclass)) {
|
||||
printf("Registering window failed\n");
|
||||
exit(1);
|
||||
}
|
||||
if(!RegisterClass(&wndclass)) {
|
||||
printf("Registering window failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
get_default_window_size(&size);
|
||||
// Create the window.
|
||||
get_default_window_size(&size);
|
||||
|
||||
HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, "gsport", "GSplus - Apple //gs Emulator",
|
||||
WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
size.cx, size.cy,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, "gsport", "GSplus - Apple //gs Emulator",
|
||||
WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
size.cx, size.cy,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
|
||||
printf("g_hwnd_main = %p, height = %d\n", hwnd, size.cx);
|
||||
GetWindowRect(hwnd, &rect);
|
||||
printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top,
|
||||
rect.right, rect.bottom);
|
||||
|
||||
// Enable non-blocking, character-at-a-time console I/O.
|
||||
// win_nonblock_read_stdin() expects this behavior.
|
||||
DWORD mode;
|
||||
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
|
||||
mode &= ~ENABLE_LINE_INPUT;
|
||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
|
||||
printf("g_hwnd_main = %p, height = %d\n", hwnd, size.cx);
|
||||
GetWindowRect(hwnd, &rect);
|
||||
printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top,
|
||||
rect.right, rect.bottom);
|
||||
|
||||
// Enable non-blocking, character-at-a-time console I/O.
|
||||
// win_nonblock_read_stdin() expects this behavior.
|
||||
DWORD mode;
|
||||
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
|
||||
mode &= ~ENABLE_LINE_INPUT;
|
||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
|
||||
|
||||
|
||||
gsportinit(hwnd);
|
||||
int ret = gsplusmain(argc, argv);
|
||||
|
||||
UnregisterClass(wndclass.lpszClassName,GetModuleHandle(NULL));
|
||||
gsportinit(hwnd);
|
||||
int ret = gsplusmain(argc, argv);
|
||||
|
||||
gsportshut();
|
||||
return ret;
|
||||
UnregisterClass(wndclass.lpszClassName,GetModuleHandle(NULL));
|
||||
|
||||
gsportshut();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void x_check_input_events()
|
||||
{
|
||||
MSG msg;
|
||||
void x_check_input_events() {
|
||||
MSG msg;
|
||||
|
||||
while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) {
|
||||
if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
printf("GetMessage returned <= 0\n");
|
||||
my_exit(2);
|
||||
}
|
||||
}
|
||||
while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) {
|
||||
if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
printf("GetMessage returned <= 0\n");
|
||||
my_exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x_redraw_status_lines()
|
||||
{
|
||||
COLORREF oldtextcolor, oldbkcolor;
|
||||
char *buf;
|
||||
int line;
|
||||
int len;
|
||||
int height;
|
||||
int margin;
|
||||
void x_redraw_status_lines() {
|
||||
COLORREF oldtextcolor, oldbkcolor;
|
||||
char *buf;
|
||||
int line;
|
||||
int len;
|
||||
int height;
|
||||
int margin;
|
||||
|
||||
height = 16;
|
||||
margin = 0;
|
||||
if (g_win_status_debug)
|
||||
{
|
||||
HDC localdc = GetDC(g_hwnd_main);
|
||||
oldtextcolor = SetTextColor(localdc, RGB(255, 255, 255));
|
||||
oldbkcolor = SetBkColor(localdc, RGB(0, 0, 0));
|
||||
for(line = 0; line < MAX_STATUS_LINES; line++) {
|
||||
buf = g_status_ptrs[line];
|
||||
if(buf != 0) {
|
||||
len = strlen(buf);
|
||||
TextOut(localdc, 10, X_A2_WINDOW_HEIGHT +
|
||||
height*line + margin, buf, len);
|
||||
}
|
||||
}
|
||||
SetTextColor(localdc, oldtextcolor);
|
||||
SetBkColor(localdc, oldbkcolor);
|
||||
ReleaseDC(g_hwnd_main,localdc);
|
||||
}
|
||||
height = 16;
|
||||
margin = 0;
|
||||
if (g_win_status_debug)
|
||||
{
|
||||
HDC localdc = GetDC(g_hwnd_main);
|
||||
oldtextcolor = SetTextColor(localdc, RGB(255, 255, 255));
|
||||
oldbkcolor = SetBkColor(localdc, RGB(0, 0, 0));
|
||||
for(line = 0; line < MAX_STATUS_LINES; line++) {
|
||||
buf = g_status_ptrs[line];
|
||||
if(buf != 0) {
|
||||
len = strlen(buf);
|
||||
TextOut(localdc, 10, X_A2_WINDOW_HEIGHT +
|
||||
height*line + margin, buf, len);
|
||||
}
|
||||
}
|
||||
SetTextColor(localdc, oldtextcolor);
|
||||
SetBkColor(localdc, oldbkcolor);
|
||||
ReleaseDC(g_hwnd_main,localdc);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
x_calc_ratio(float ratiox,float ratioy)
|
||||
{
|
||||
return 0; // not stretched
|
||||
int x_calc_ratio(float ratiox,float ratioy) {
|
||||
return 0; // not stretched
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
2125
src/xdriver.c
2125
src/xdriver.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue