using code beautifier (uncrustify), possibly most controversial commit ever\?

This commit is contained in:
Dagen Brock 2018-08-13 12:22:40 -05:00
parent a509cc0a3c
commit 65f280569c
58 changed files with 32660 additions and 34069 deletions

3
.gitignore vendored
View File

@ -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/

19
assets/uncrustify.cfg Normal file
View File

@ -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

3329
src/adb.c

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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;

View File

@ -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:
*/

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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, &current->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, &current->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(&ether->source, &HW_LOCAL, sizeof(ether->source)) != 0) && /* Ignore packets sent from our node. */
(memcmp(&ether->dest, &HW_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
memcmp(&ether->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(&ether->source, &HW_LOCAL, sizeof(ether->source)) != 0) && /* Ignore packets sent from our node. */
(memcmp(&ether->dest, &HW_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
memcmp(&ether->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, &ether->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, &ether->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();
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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__;

File diff suppressed because it is too large Load Diff

View File

@ -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++ = '=';

View File

@ -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

1990
src/dis.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -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

3746
src/iwm.c

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

2669
src/scc.c

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() { }

View File

@ -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
}

View File

@ -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");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff