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 # Screenshot dir
screens/ 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "../../defc.h" #include "../../defc.h"
#include "../../protos.h" #include "../../protos.h"
@ -15,13 +15,13 @@
#include <string.h> #include <string.h>
#include "gsportos2.h" /* Resource symbolic identifiers*/ #include "gsportos2.h" /* Resource symbolic identifiers*/
HAB g_hab; /* PM anchor block handle */ HAB g_hab; /* PM anchor block handle */
PSZ pszErrMsg; PSZ pszErrMsg;
QMSG qmsg; /* Message from message queue */ QMSG qmsg; /* Message from message queue */
HWND g_hwnd_frame = NULLHANDLE; /* Frame window handle */ HWND g_hwnd_frame = NULLHANDLE; /* Frame window handle */
HWND g_hwnd_client = NULLHANDLE; /* Client area 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; extern int Verbose;
@ -32,15 +32,15 @@ int g_screen_mdepth = 0;
extern int g_quit_sim_now; extern int g_quit_sim_now;
int g_use_shmem = 1; int g_use_shmem = 1;
int g_has_focus = 0; int g_has_focus = 0;
int g_auto_repeat_on = -1; int g_auto_repeat_on = -1;
extern Kimage g_mainwin_kimage; 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_sides_refresh_needed;
extern int g_border_special_refresh_needed; extern int g_border_special_refresh_needed;
@ -68,87 +68,79 @@ extern char *g_status_ptrs[MAX_STATUS_LINES];
VOID DispErrorMessage(); VOID DispErrorMessage();
int int win_nonblock_read_stdin(int fd, char *bufptr, int len) {
win_nonblock_read_stdin(int fd, char *bufptr, int len)
{
return 0; return 0;
} }
void void x_dialog_create_gsport_conf(const char *str) {
x_dialog_create_gsport_conf(const char *str)
{
} }
int int x_show_alert(int is_fatal, const char *str) {
x_show_alert(int is_fatal, const char *str) return 0;
{
return 0;
} }
int int main(int argc, char **argv) {
main(int argc, char **argv) DEVOPENSTRUC pszData;
{ ULONG flCreate; /* Window creation control flags*/
DEVOPENSTRUC pszData; int height;
ULONG flCreate; /* Window creation control flags*/ SIZEL sizel;
int height;
SIZEL sizel;
if ((g_hab = WinInitialize(0)) == 0L) /* Initialize PM */ if ((g_hab = WinInitialize(0)) == 0L) /* Initialize PM */
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
if ((g_hmq = WinCreateMsgQueue( g_hab, 0 )) == 0L)/* Create a msg queue */ if ((g_hmq = WinCreateMsgQueue( g_hab, 0 )) == 0L) /* Create a msg queue */
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
if (!WinRegisterClass( /* Register window class */ if (!WinRegisterClass( /* Register window class */
g_hab, /* Anchor block handle */ g_hab, /* Anchor block handle */
(PSZ)"MyWindow", /* Window class name */ (PSZ)"MyWindow", /* Window class name */
(PFNWP)MyWindowProc, /* Address of window procedure */ (PFNWP)MyWindowProc, /* Address of window procedure */
CS_SIZEREDRAW, /* Class style */ CS_SIZEREDRAW, /* Class style */
0 /* No extra window words */ 0 /* No extra window words */
)) ))
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES*16); height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES*16);
g_main_height = height; g_main_height = height;
flCreate = FCF_STANDARD & /* Set frame control flags to */ flCreate = FCF_STANDARD & /* Set frame control flags to */
~FCF_SHELLPOSITION; /* standard except for shell */ ~FCF_SHELLPOSITION; /* standard except for shell */
/* positioning. */ /* positioning. */
if ((g_hwnd_frame = WinCreateStdWindow( if ((g_hwnd_frame = WinCreateStdWindow(
HWND_DESKTOP, /* Desktop window is parent */ HWND_DESKTOP, /* Desktop window is parent */
0, /* STD. window styles */ 0, /* STD. window styles */
&flCreate, /* Frame control flag */ &flCreate, /* Frame control flag */
"MyWindow", /* Client window class name */ "MyWindow", /* Client window class name */
"", /* No window text */ "", /* No window text */
0, /* No special class style */ 0, /* No special class style */
(HMODULE)0L, /* Resource is in .EXE file */ (HMODULE)0L, /* Resource is in .EXE file */
ID_WINDOW, /* Frame window identifier */ ID_WINDOW, /* Frame window identifier */
&g_hwnd_client /* Client window handle */ &g_hwnd_client /* Client window handle */
)) == 0L) )) == 0L)
os2_abort(HWND_DESKTOP, HWND_DESKTOP); /* Terminate the application */ 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 */ if (!WinSetWindowPos( g_hwnd_frame, /* Shows and activates frame */
HWND_TOP, /* window at position 100, 100, */ HWND_TOP, /* window at position 100, 100, */
100, 100, X_A2_WINDOW_WIDTH, height, /* and size 200, 200. */ 100, 100, X_A2_WINDOW_WIDTH, height, /* and size 200, 200. */
SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW
)) ))
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */ os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
g_hdc_screen = WinOpenWindowDC(g_hwnd_client); g_hdc_screen = WinOpenWindowDC(g_hwnd_client);
sizel.cx = X_A2_WINDOW_WIDTH; sizel.cx = X_A2_WINDOW_WIDTH;
sizel.cy = height; sizel.cy = height;
g_hps_screen = GpiCreatePS(g_hab,g_hdc_screen, &sizel, PU_PELS | GPIF_LONG | GPIA_ASSOC); 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_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_hps_memory = GpiCreatePS(g_hab,g_hdc_memory, &sizel, PU_ARBITRARY | GPIT_MICRO | GPIA_ASSOC);
// Call gsplusmain // Call gsplusmain
return gsplusmain(argc, argv); return gsplusmain(argc, argv);
} }
@ -163,10 +155,9 @@ SIZEL sizel;
* the message command and parameters. * the message command and parameters.
* *
*************************************************************************/ *************************************************************************/
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) {
{ HPS hps;
HPS hps; RECTL rcl;
RECTL rcl;
switch( msg ) switch( msg )
{ {
@ -185,7 +176,7 @@ RECTL rcl;
* When Exit is chosen, the application posts itself a WM_CLOSE * When Exit is chosen, the application posts itself a WM_CLOSE
* message. * message.
*/ */
{ {
USHORT command; /* WM_COMMAND command value */ USHORT command; /* WM_COMMAND command value */
command = SHORT1FROMMP(mp1); /* Extract the command value */ command = SHORT1FROMMP(mp1); /* Extract the command value */
switch (command) switch (command)
@ -198,7 +189,7 @@ RECTL rcl;
} }
break; break;
} }
case WM_ERASEBACKGROUND: case WM_ERASEBACKGROUND:
/* /*
* Return TRUE to request PM to paint the window background * 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. * Window contents are drawn here in WM_PAINT processing.
*/ */
hps = WinBeginPaint(hwnd, NULLHANDLE, &rcl); hps = WinBeginPaint(hwnd, NULLHANDLE, &rcl);
WinEndPaint(hps); WinEndPaint(hps);
g_needfullrefreshfornextframe = 1; g_needfullrefreshfornextframe = 1;
break; break;
case WM_CLOSE: case WM_CLOSE:
/* /*
* This is the place to put your termination routines * This is the place to put your termination routines
*/ */
WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 ); /* Cause termination*/ WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 ); /* Cause termination*/
exit(0); exit(0);
break; break;
default: default:
/* /*
@ -232,262 +223,232 @@ RECTL rcl;
return (MRESULT)FALSE; return (MRESULT)FALSE;
} /* End of MyWindowProc */ } /* End of MyWindowProc */
void void check_input_events() {
check_input_events()
{
/* /*
* Get and dispatch messages from the application message queue * Get and dispatch messages from the application message queue
* until WinGetMsg returns FALSE, indicating a WM_QUIT message. * until WinGetMsg returns FALSE, indicating a WM_QUIT message.
*/ */
while(WinPeekMsg(g_hab, &qmsg, g_hwnd_frame, 0, 0, PM_NOREMOVE)) { while(WinPeekMsg(g_hab, &qmsg, g_hwnd_frame, 0, 0, PM_NOREMOVE)) {
if(WinGetMsg(g_hab, &qmsg, 0L, 0, 0) > 0) { if(WinGetMsg(g_hab, &qmsg, 0L, 0, 0) > 0) {
//TranslateMessage(&qmsg); //TranslateMessage(&qmsg);
WinDispatchMsg(g_hab, &qmsg); WinDispatchMsg(g_hab, &qmsg);
} else { } else {
printf("GetMessage returned <= 0\n"); printf("GetMessage returned <= 0\n");
my_exit(2); my_exit(2);
} }
} }
} }
void void x_update_color(int col_num, int red, int green, int blue, word32 rgb) {
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
{
} }
void void x_update_physical_colormap() {
x_update_physical_colormap()
{
} }
void void show_xcolor_array() {
show_xcolor_array()
{
} }
void void xdriver_end() {
xdriver_end() printf("OS/2 driver_end\n");
{
printf("OS/2 driver_end\n");
} }
void void x_get_kimage(Kimage *kimage_ptr) {
x_get_kimage(Kimage *kimage_ptr) byte *ptr;
{ int width;
byte *ptr; int height;
int width; int depth, mdepth;
int height; int size;
int depth, mdepth;
int size;
width = kimage_ptr->width_req; width = kimage_ptr->width_req;
height = kimage_ptr->height; height = kimage_ptr->height;
depth = kimage_ptr->depth; depth = kimage_ptr->depth;
mdepth = kimage_ptr->mdepth; mdepth = kimage_ptr->mdepth;
size = 0; size = 0;
if(depth == g_screen_depth) { if(depth == g_screen_depth) {
/* Use g_bmapinfo_ptr, adjusting width, height */ /* Use g_bmapinfo_ptr, adjusting width, height */
g_bmaphdr_ptr->cx = width; g_bmaphdr_ptr->cx = width;
g_bmaphdr_ptr->cy = height; g_bmaphdr_ptr->cy = height;
kimage_ptr->dev_handle = GpiCreateBitmap( kimage_ptr->dev_handle = GpiCreateBitmap(
(HPS)g_hps_memory, (PBITMAPINFOHEADER2)g_bmaphdr_ptr, (HPS)g_hps_memory, (PBITMAPINFOHEADER2)g_bmaphdr_ptr,
0L, (PBYTE)kimage_ptr->data_ptr, 0L, (PBYTE)kimage_ptr->data_ptr,
(PBITMAPINFO2)g_bmapinfo_ptr); (PBITMAPINFO2)g_bmapinfo_ptr);
size = (width*height*mdepth) >> 3; size = (width*height*mdepth) >> 3;
ptr = (byte *)malloc(size); ptr = (byte *)malloc(size);
if(ptr == 0) { if(ptr == 0) {
printf("malloc for data failed, mdepth: %d\n", mdepth); printf("malloc for data failed, mdepth: %d\n", mdepth);
exit(2); exit(2);
} }
kimage_ptr->data_ptr = ptr; kimage_ptr->data_ptr = ptr;
} else { } else {
/* allocate buffers for video.c to draw into */ /* allocate buffers for video.c to draw into */
size = (width*height*mdepth) >> 3; size = (width*height*mdepth) >> 3;
ptr = (byte *)malloc(size); ptr = (byte *)malloc(size);
if(ptr == 0) { if(ptr == 0) {
printf("malloc for data failed, mdepth: %d\n", mdepth); printf("malloc for data failed, mdepth: %d\n", mdepth);
exit(2); 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 void dev_video_init() {
dev_video_init() int lores_col;
{ int i;
int lores_col;
int i;
printf("Preparing graphics system\n"); printf("Preparing graphics system\n");
g_screen_depth = 24; g_screen_depth = 24;
g_screen_mdepth = 32; g_screen_mdepth = 32;
g_bmapinfo_ptr = (BITMAPINFO2 *)malloc(sizeof(BITMAPINFOHEADER2)); g_bmapinfo_ptr = (BITMAPINFO2 *)malloc(sizeof(BITMAPINFOHEADER2));
g_bmaphdr_ptr = (BITMAPINFOHEADER2 *)g_bmapinfo_ptr; g_bmaphdr_ptr = (BITMAPINFOHEADER2 *)g_bmapinfo_ptr;
g_bmaphdr_ptr->cbFix = sizeof(BITMAPINFOHEADER2); g_bmaphdr_ptr->cbFix = sizeof(BITMAPINFOHEADER2);
g_bmaphdr_ptr->cx = A2_WINDOW_WIDTH; g_bmaphdr_ptr->cx = A2_WINDOW_WIDTH;
g_bmaphdr_ptr->cy = A2_WINDOW_HEIGHT; g_bmaphdr_ptr->cy = A2_WINDOW_HEIGHT;
g_bmaphdr_ptr->cPlanes = 1; g_bmaphdr_ptr->cPlanes = 1;
g_bmaphdr_ptr->cBitCount = g_screen_mdepth; g_bmaphdr_ptr->cBitCount = g_screen_mdepth;
g_bmaphdr_ptr->ulCompression = BCA_UNCOMP; g_bmaphdr_ptr->ulCompression = BCA_UNCOMP;
g_bmaphdr_ptr->cclrUsed = 0; g_bmaphdr_ptr->cclrUsed = 0;
video_get_kimages(); video_get_kimages();
if(g_screen_depth != 8) { if(g_screen_depth != 8) {
// Allocate g_mainwin_kimage // Allocate g_mainwin_kimage
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
g_screen_mdepth); g_screen_mdepth);
} }
for(i = 0; i < 256; i++) { for(i = 0; i < 256; i++) {
lores_col = g_lores_colors[i & 0xf]; lores_col = g_lores_colors[i & 0xf];
video_update_color_raw(i, lores_col); video_update_color_raw(i, lores_col);
g_a2palette_8to1624[i] = g_palette_8to1624[i]; 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"); printf("Done with dev_video_init\n");
fflush(stdout); fflush(stdout);
} }
void void x_redraw_status_lines() {
x_redraw_status_lines()
{
int line,len,height; int line,len,height;
POINTL pt; POINTL pt;
char *buf; char *buf;
printf("x_redraw_status_lines() called\n"); printf("x_redraw_status_lines() called\n");
/* /*
if (g_status_ptrs[0] != NULL) if (g_status_ptrs[0] != NULL)
{ {
height = 16; height = 16;
pt.x = 5; pt.y = 0; pt.x = 5; pt.y = 0;
GpiSetColor( g_hps_screen, CLR_NEUTRAL ); GpiSetColor( g_hps_screen, CLR_NEUTRAL );
GpiSetBackColor( g_hps_screen, CLR_BACKGROUND ); GpiSetBackColor( g_hps_screen, CLR_BACKGROUND );
GpiSetBackMix( g_hps_screen, BM_OVERPAINT ); GpiSetBackMix( g_hps_screen, BM_OVERPAINT );
for (line = 0; line < MAX_STATUS_LINES; line++) for (line = 0; line < MAX_STATUS_LINES; line++)
{ {
buf = g_status_ptrs[line]; buf = g_status_ptrs[line];
if (buf != 0) if (buf != 0)
{ {
pt.y = height * (line+1); pt.y = height * (line+1);
len = strlen(buf); len = strlen(buf);
GpiCharStringAt( g_hps_screen, &pt, (LONG)strlen( buf ), buf ); GpiCharStringAt( g_hps_screen, &pt, (LONG)strlen( buf ), buf );
} }
} }
} }
*/ */
} }
void void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height) {
int width, int height) RECTL rc;
{ POINTL pt[4];
RECTL rc; HBITMAP hbmOld, hbmNew;
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); 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].x = destx; /* Target X1 */
pt[0].y = desty+(MAX_STATUS_LINES*16); /* Target Y1 */ pt[0].y = desty+(MAX_STATUS_LINES*16); /* Target Y1 */
pt[1].x = destx+width; /* Target X2 */ 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[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].x = srcx; /* Source X */
pt[2].y = srcy; /* Source Y */ pt[2].y = srcy; /* Source Y */
pt[3].x = srcx+width; pt[3].x = srcx+width;
pt[3].y = srcy+height; pt[3].y = srcy+height;
if (width == 560) if (width == 560)
{ {
/* Paint a known-good bitmap until we can figure out why images aren't showing up */ /* 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); hbmNew = GpiLoadBitmap(g_hps_memory,NULLHANDLE,ID_BITMAP,560,400);
hbmOld = GpiSetBitmap(g_hps_memory, hbmNew); hbmOld = GpiSetBitmap(g_hps_memory, hbmNew);
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE); GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
GpiSetBitmap(g_hps_memory, hbmOld); GpiSetBitmap(g_hps_memory, hbmOld);
GpiDeleteBitmap(hbmNew); GpiDeleteBitmap(hbmNew);
} }
else else
{ {
hbmOld = GpiSetBitmap(g_hps_memory, (HBITMAP)kimage_ptr->dev_handle); hbmOld = GpiSetBitmap(g_hps_memory, (HBITMAP)kimage_ptr->dev_handle);
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE); GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
GpiSetBitmap(g_hps_memory, hbmOld); GpiSetBitmap(g_hps_memory, hbmOld);
} }
} }
// OG Adding release // OG Adding release
void x_release_kimage(Kimage* kimage_ptr) void x_release_kimage(Kimage* kimage_ptr) {
{ if (kimage_ptr->dev_handle == (void*)-1)
if (kimage_ptr->dev_handle == (void*)-1) {
{ free(kimage_ptr->data_ptr);
free(kimage_ptr->data_ptr); kimage_ptr->data_ptr = NULL;
kimage_ptr->data_ptr = NULL; }
} else
else {
{ }
}
} }
void void x_push_done() {
x_push_done()
{
} }
void void x_auto_repeat_on(int must) {
x_auto_repeat_on(int must)
{
} }
void void x_auto_repeat_off(int must) {
x_auto_repeat_off(int must)
{
} }
void void x_hide_pointer(int do_hide) {
x_hide_pointer(int do_hide)
{
} }
void void x_full_screen(int do_full) {
x_full_screen(int do_full) return;
{
return;
} }
int x_calc_ratio(float ratiox,float ratioy) int x_calc_ratio(float ratiox,float ratioy) {
{ return 0; // not stretched
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 */ /* The error message is displayed using a message box */
/* */ /* */
/**************************************************************************/ /**************************************************************************/
VOID DispErrorMessage() VOID DispErrorMessage() {
{ PERRINFO pErrInfoBlk;
PERRINFO pErrInfoBlk; PSZ pszOffSet, pszErrMsg;
PSZ pszOffSet, pszErrMsg; ERRORID ErrorId;
ERRORID ErrorId; PCH ErrorStr;
PCH ErrorStr;
ErrorId = WinGetLastError(g_hab); ErrorId = WinGetLastError(g_hab);
if ((pErrInfoBlk = WinGetErrorInfo(g_hab)) != (PERRINFO)NULL) if ((pErrInfoBlk = WinGetErrorInfo(g_hab)) != (PERRINFO)NULL)
{ {
pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg; pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet); pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet);
WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */ WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
g_hwnd_frame, /* Owner window is our frame */ g_hwnd_frame, /* Owner window is our frame */
pszErrMsg, /* PMWIN Error message */ pszErrMsg, /* PMWIN Error message */
"Error", /* Title bar message */ "Error", /* Title bar message */
0, /* Message identifier */ 0, /* Message identifier */
MB_MOVEABLE | MB_CANCEL ); /* Flags */ MB_MOVEABLE | MB_CANCEL ); /* Flags */
WinFreeErrorInfo(pErrInfoBlk); WinFreeErrorInfo(pErrInfoBlk);
} }
} }
void void os2_abort(HWND g_hwnd_frame, HWND g_hwnd_client) {
os2_abort(HWND g_hwnd_frame, HWND g_hwnd_client)
{
exit(-1); exit(-1);
} }

View File

@ -1,8 +1,8 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
int g_preferred_rate = 48000; int g_preferred_rate = 48000;

View File

@ -18,48 +18,45 @@
* 02111-1307 USA. * 02111-1307 USA.
* *
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "dirport.h" #include "dirport.h"
DIR *opendir (char *path) DIR *opendir (char *path) {
{ APIRET ulrc;
APIRET ulrc; ULONG cnt = 1;
ULONG cnt = 1; DIR *dir;
DIR *dir; char *name;
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);
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); 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 snprintf.c
- a portable implementation of snprintf, - a portable implementation of snprintf,
including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
snprintf is a routine to convert numeric and string arguments to snprintf is a routine to convert numeric and string arguments to
formatted strings. It is similar to sprintf(3) provided in a system's formatted strings. It is similar to sprintf(3) provided in a system's
C library, yet it requires an additional argument - the buffer size - 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 not or do provide an inadequate (slow or idiosyncratic) version, which
calls for a portable implementation of this routine. calls for a portable implementation of this routine.
Author Author
Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000 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) \ #define fast_memcpy(d,s,n) \
{ register size_t nn = (size_t)(n); \ { register size_t nn = (size_t)(n); \
if (nn >= breakeven_point) memcpy((d), (s), nn); \ 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; \ register char *dd; register const char *ss; \
for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
#define fast_memset(d,c,n) \ #define fast_memset(d,c,n) \
{ register size_t nn = (size_t)(n); \ { register size_t nn = (size_t)(n); \
if (nn >= breakeven_point) memset((d), (int)(c), nn); \ 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); \ register char *dd; register const int cc=(int)(c); \
for (dd=(d); nn>0; nn--) *dd++ = cc; } } 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_list ap2;
va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ 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*/ 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 */ assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
*ptr = (char *) malloc(str_m = (size_t)str_l + 1); *ptr = (char *) malloc(str_m = (size_t)str_l + 1);
if (*ptr == NULL) { errno = ENOMEM; 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_list ap2;
va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ 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*/ 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 */ 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 ((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 */ /* 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 = ""; if (!p) p = "";
while (*p) { while (*p) {
if (*p != '%') { if (*p != '%') {
/* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */
/* but the following code achieves better performance for cases /* but the following code achieves better performance for cases
* where format string is long and contains few conversions */ * where format string is long and contains few conversions */
const char *q = strchr(p+1,'%'); const char *q = strchr(p+1,'%');
size_t n = !q ? strlen(p) : (q-p); size_t n = !q ? strlen(p) : (q-p);
if (str_l < str_m) { if (str_l < str_m) {
size_t avail = str_m-str_l; 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; p += n; str_l += n;
} else { } 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 size_t str_arg_l; /* natural field width of arg without padding
and sign */ and sign */
unsigned char uchar_arg; unsigned char uchar_arg;
/* unsigned char argument value - only defined for c conversion. /* unsigned char argument value - only defined for c conversion.
N.B. standard explicitly states the char argument for N.B. standard explicitly states the char argument for
the c conversion is unsigned */ the c conversion is unsigned */
size_t number_of_zeros_to_pad = 0; size_t number_of_zeros_to_pad = 0;
/* number of zeros to be inserted for numeric conversions /* number of zeros to be inserted for numeric conversions
as required by the precision or minimal field width */ as required by the precision or minimal field width */
size_t zero_padding_insertion_ind = 0; 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'; 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 = credits;/* just to make compiler happy (defined but not used)*/
str_arg = NULL; str_arg = NULL;
starting_p = p; p++; /* skip '%' */ starting_p = p; p++; /* skip '%' */
/* parse flags */ /* parse flags */
while (*p == '0' || *p == '-' || *p == '+' || while (*p == '0' || *p == '-' || *p == '+' ||
*p == ' ' || *p == '#' || *p == '\'') { *p == ' ' || *p == '#' || *p == '\'') {
switch (*p) { switch (*p) {
case '0': zero_padding = 1; break; case '0': zero_padding = 1; break;
case '-': justify_left = 1; break; case '-': justify_left = 1; break;
case '+': force_sign = 1; space_for_positive = 0; break; case '+': force_sign = 1; space_for_positive = 0; break;
case ' ': force_sign = 1; case ' ': force_sign = 1;
/* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
#ifdef PERL_COMPATIBLE #ifdef PERL_COMPATIBLE
/* ... but in Perl the last of ' ' and '+' applies */ /* ... but in Perl the last of ' ' and '+' applies */
space_for_positive = 1; space_for_positive = 1;
#endif #endif
break; break;
case '#': alternate_form = 1; break; case '#': alternate_form = 1; break;
case '\'': break; case '\'': break;
} }
p++; 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 == '*') { if (*p == '*') {
int j; int j;
p++; j = va_arg(ap, int); 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'); while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
min_field_width = uj; min_field_width = uj;
} }
/* parse precision */ /* parse precision */
if (*p == '.') { if (*p == '.') {
p++; precision_specified = 1; p++; precision_specified = 1;
if (*p == '*') { 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; if (j >= 0) precision = j;
else { else {
precision_specified = 0; precision = 0; precision_specified = 0; precision = 0;
/* NOTE: /* NOTE:
* Solaris 2.6 man page claims that in this case the precision * 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 * 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, * claim that this case should be treated as unspecified precision,
* which is what we do here. * which is what we do here.
*/ */
} }
} else if (isdigit((int)(*p))) { } else if (isdigit((int)(*p))) {
/* size_t could be wider than unsigned int; /* 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; precision = uj;
} }
} }
/* parse 'h', 'l' and 'll' length modifiers */ /* parse 'h', 'l' and 'll' length modifiers */
if (*p == 'h' || *p == 'l') { if (*p == 'h' || *p == 'l') {
length_modifier = *p; p++; length_modifier = *p; p++;
if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ 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; fmt_spec = *p;
/* common synonyms: */ /* common synonyms: */
switch (fmt_spec) { switch (fmt_spec) {
case 'i': fmt_spec = 'd'; break; case 'i': fmt_spec = 'd'; break;
case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
default: break; default: break;
} }
/* get parameter value, do initial processing */ /* get parameter value, do initial processing */
switch (fmt_spec) { switch (fmt_spec) {
case '%': /* % behaves similar to 's' regarding flags and field widths */ case '%': /* % behaves similar to 's' regarding flags and field widths */
case 'c': /* c 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 's': case 's':
str_arg = va_arg(ap, const char *); length_modifier = '\0'; /* wint_t and wchar_t not supported */
if (!str_arg) str_arg_l = 0; /* the result of zero padding flag with non-numeric conversion specifier*/
/* make sure not to address string beyond the specified precision !!! */ /* is undefined. Solaris and HPUX 10 does zero padding in this case, */
else if (!precision_specified) str_arg_l = strlen(str_arg); /* Digital Unix and Linux does not. */
/* truncate string if necessary as requested by precision */ #if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
else if (precision == 0) str_arg_l = 0; zero_padding = 0; /* turn zero padding off for string conversions */
else { #endif
/* memchr on HP does not like n > 2^31 !!! */ str_arg_l = 1;
const char *q = memchr(str_arg, '\0', switch (fmt_spec) {
precision <= 0x7fffffff ? precision : 0x7fffffff); case '%':
str_arg_l = !q ? precision : (q-str_arg); 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; break;
default: break; case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
} /* NOTE: the u, o, x, X and p conversion specifiers imply
break; 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'), /* 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 greater than zero (or nonzero for unsigned arguments),
-1 if negative (unsigned argument is never negative) */ -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 */ /* 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 */ /* only defined for length modifier l */
void *ptr_arg = NULL; void *ptr_arg = NULL;
/* pointer argument value -only defined for p conversion */ /* pointer argument value -only defined for p conversion */
#ifdef SNPRINTF_LONGLONG_SUPPORT #ifdef SNPRINTF_LONGLONG_SUPPORT
long long int long_long_arg = 0; long long int long_long_arg = 0;
unsigned long long int ulong_long_arg = 0; unsigned long long int ulong_long_arg = 0;
/* only defined for length modifier ll */ /* only defined for length modifier ll */
#endif #endif
if (fmt_spec == 'p') { if (fmt_spec == 'p') {
/* HPUX 10: An l, h, ll or L before any other conversion character /* HPUX 10: An l, h, ll or L before any other conversion character
* (other than d, i, u, o, x, or X) is ignored. * (other than d, i, u, o, x, or X) is ignored.
* Digital Unix: * Digital Unix:
* not specified, but seems to behave as HPUX does. * not specified, but seems to behave as HPUX does.
* Solaris: If an h, l, or L appears before any other conversion * Solaris: If an h, l, or L appears before any other conversion
* specifier (other than d, i, u, o, x, or X), the behavior * specifier (other than d, i, u, o, x, or X), the behavior
* is undefined. (Actually %hp converts only 16-bits of address * is undefined. (Actually %hp converts only 16-bits of address
* and %llp treats address as 64-bit data which is incompatible * and %llp treats address as 64-bit data which is incompatible
* with (void *) argument on a 32-bit system). * with (void *) argument on a 32-bit system).
*/ */
#ifdef SOLARIS_COMPATIBLE #ifdef SOLARIS_COMPATIBLE
# ifdef SOLARIS_BUG_COMPATIBLE # ifdef SOLARIS_BUG_COMPATIBLE
/* keep length modifiers even if it represents 'll' */ /* keep length modifiers even if it represents 'll' */
# else # else
if (length_modifier == '2') length_modifier = '\0'; if (length_modifier == '2') length_modifier = '\0';
# endif # endif
#else #else
length_modifier = '\0'; length_modifier = '\0';
#endif #endif
ptr_arg = va_arg(ap, void *); ptr_arg = va_arg(ap, void *);
if (ptr_arg != NULL) arg_sign = 1; if (ptr_arg != NULL) arg_sign = 1;
} else if (fmt_spec == 'd') { /* signed */ } else if (fmt_spec == 'd') { /* signed */
switch (length_modifier) { switch (length_modifier) {
case '\0': case '\0':
case 'h': case 'h':
/* It is non-portable to specify a second argument of char or short /* It is non-portable to specify a second argument of char or short
* to va_arg, because arguments seen by the called function * to va_arg, because arguments seen by the called function
* are not char or short. C converts char and short arguments * are not char or short. C converts char and short arguments
* to int before passing them to a function. * to int before passing them to a function.
*/ */
int_arg = va_arg(ap, int); int_arg = va_arg(ap, int);
if (int_arg > 0) arg_sign = 1; if (int_arg > 0) arg_sign = 1;
else if (int_arg < 0) arg_sign = -1; else if (int_arg < 0) arg_sign = -1;
break; break;
case 'l': case 'l':
long_arg = va_arg(ap, long int); long_arg = va_arg(ap, long int);
if (long_arg > 0) arg_sign = 1; if (long_arg > 0) arg_sign = 1;
else if (long_arg < 0) arg_sign = -1; else if (long_arg < 0) arg_sign = -1;
break; break;
#ifdef SNPRINTF_LONGLONG_SUPPORT #ifdef SNPRINTF_LONGLONG_SUPPORT
case '2': case '2':
long_long_arg = va_arg(ap, long long int); long_long_arg = va_arg(ap, long long int);
if (long_long_arg > 0) arg_sign = 1; if (long_long_arg > 0) arg_sign = 1;
else if (long_long_arg < 0) arg_sign = -1; else if (long_long_arg < 0) arg_sign = -1;
break; break;
#endif #endif
} }
} else { /* unsigned */ } else { /* unsigned */
switch (length_modifier) { switch (length_modifier) {
case '\0': case '\0':
case 'h': case 'h':
uint_arg = va_arg(ap, unsigned int); uint_arg = va_arg(ap, unsigned int);
if (uint_arg) arg_sign = 1; if (uint_arg) arg_sign = 1;
break; break;
case 'l': case 'l':
ulong_arg = va_arg(ap, unsigned long int); ulong_arg = va_arg(ap, unsigned long int);
if (ulong_arg) arg_sign = 1; if (ulong_arg) arg_sign = 1;
break; break;
#ifdef SNPRINTF_LONGLONG_SUPPORT #ifdef SNPRINTF_LONGLONG_SUPPORT
case '2': case '2':
ulong_long_arg = va_arg(ap, unsigned long long int); ulong_long_arg = va_arg(ap, unsigned long long int);
if (ulong_long_arg) arg_sign = 1; if (ulong_long_arg) arg_sign = 1;
break; break;
#endif #endif
}
} }
} str_arg = tmp; str_arg_l = 0;
str_arg = tmp; str_arg_l = 0; /* NOTE:
/* NOTE: * For d, i, u, o, x, and X conversions, if precision is specified,
* 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,
* 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.
* Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. */
*/
#ifndef PERL_COMPATIBLE #ifndef PERL_COMPATIBLE
if (precision_specified) zero_padding = 0; if (precision_specified) zero_padding = 0;
#endif #endif
if (fmt_spec == 'd') { if (fmt_spec == 'd') {
if (force_sign && arg_sign >= 0) if (force_sign && arg_sign >= 0)
tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
/* leave negative numbers for sprintf to handle, /* leave negative numbers for sprintf to handle,
to avoid handling tricky cases like (short int)(-32768) */ to avoid handling tricky cases like (short int)(-32768) */
#ifdef LINUX_COMPATIBLE #ifdef LINUX_COMPATIBLE
} else if (fmt_spec == 'p' && force_sign && arg_sign > 0) { } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) {
tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
#endif #endif
} else if (alternate_form) { } else if (alternate_form) {
if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
{ tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } { 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 #ifdef HPUX_COMPATIBLE
else if (fmt_spec == 'p' else if (fmt_spec == 'p'
/* HPUX 10: for an alternate form of p conversion, /* HPUX 10: for an alternate form of p conversion,
* a nonzero result is prefixed by 0x. */ * a nonzero result is prefixed by 0x. */
#ifndef HPUX_BUG_COMPATIBLE #ifndef HPUX_BUG_COMPATIBLE
/* Actually it uses 0x prefix even for a zero value. */ /* Actually it uses 0x prefix even for a zero value. */
&& arg_sign != 0 && arg_sign != 0
#endif #endif
) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; } ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; }
#endif #endif
} }
zero_padding_insertion_ind = str_arg_l; zero_padding_insertion_ind = str_arg_l;
if (!precision_specified) precision = 1; /* default precision is 1 */ if (!precision_specified) precision = 1; /* default precision is 1 */
if (precision == 0 && arg_sign == 0 if (precision == 0 && arg_sign == 0
#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE) #if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE)
&& fmt_spec != 'p' && fmt_spec != 'p'
/* HPUX 10 man page claims: With conversion character p the result of /* 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. * converting a zero value with a precision of zero is a null string.
* Actually HP returns all zeroes, and Linux returns "(nil)". */ * Actually HP returns all zeroes, and Linux returns "(nil)". */
#endif #endif
) { ) {
/* converted to null string */ /* converted to null string */
/* When zero value is formatted with an explicit precision 0, /* When zero value is formatted with an explicit precision 0,
the resulting formatted string is empty (d, i, u, o, x, X, p). */ the resulting formatted string is empty (d, i, u, o, x, X, p). */
} else { } else {
char f[5]; int f_l = 0; char f[5]; int f_l = 0;
f[f_l++] = '%'; /* construct a simple format string for sprintf */ f[f_l++] = '%'; /* construct a simple format string for sprintf */
if (!length_modifier) { } if (!length_modifier) { }
else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
else f[f_l++] = length_modifier; else f[f_l++] = length_modifier;
f[f_l++] = fmt_spec; f[f_l++] = '\0'; f[f_l++] = fmt_spec; f[f_l++] = '\0';
if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
else if (fmt_spec == 'd') { /* signed */ else if (fmt_spec == 'd') { /* signed */
switch (length_modifier) { switch (length_modifier) {
case '\0': case '\0':
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; 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; case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
#ifdef SNPRINTF_LONGLONG_SUPPORT #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 #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 */ /* include the optional minus sign and possible "0x"
switch (length_modifier) { in the region before the zero padding insertion point */
case '\0': if (zero_padding_insertion_ind < str_arg_l &&
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; tmp[zero_padding_insertion_ind] == '-') {
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; zero_padding_insertion_ind++;
#ifdef SNPRINTF_LONGLONG_SUPPORT }
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; if (zero_padding_insertion_ind+1 < str_arg_l &&
#endif 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" { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
in the region before the zero padding insertion point */ if (alternate_form && fmt_spec == 'o'
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'
#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */ #ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */
&& (str_arg_l > 0) && (str_arg_l > 0)
#endif #endif
#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */ #ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */
#else #else
/* unless zero is already the first character */ /* unless zero is already the first character */
&& !(zero_padding_insertion_ind < str_arg_l && !(zero_padding_insertion_ind < str_arg_l
&& tmp[zero_padding_insertion_ind] == '0') && tmp[zero_padding_insertion_ind] == '0')
#endif #endif
) { /* assure leading zero for alternate-form octal numbers */ ) { /* assure leading zero for alternate-form octal numbers */
if (!precision_specified || precision < num_of_digits+1) { if (!precision_specified || precision < num_of_digits+1) {
/* precision is increased to force the first character to be zero, /* precision is increased to force the first character to be zero,
except if a zero value is formatted with an explicit precision except if a zero value is formatted with an explicit precision
of zero */ of zero */
precision = num_of_digits+1; precision_specified = 1; 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? */ break;
if (num_of_digits < precision)
number_of_zeros_to_pad = precision - num_of_digits;
} }
/* zero padding to specified minimal field width? */ default: /* unrecognized conversion specifier, keep format string as-is*/
if (!justify_left && zero_padding) { zero_padding = 0; /* turn zero padding off for non-numeric convers. */
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. */
#ifndef DIGITAL_UNIX_COMPATIBLE #ifndef DIGITAL_UNIX_COMPATIBLE
justify_left = 1; min_field_width = 0; /* reset flags */ justify_left = 1; min_field_width = 0; /* reset flags */
#endif #endif
#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) #if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE)
/* keep the entire format string unchanged */ /* keep the entire format string unchanged */
str_arg = starting_p; str_arg_l = p - starting_p; str_arg = starting_p; str_arg_l = p - starting_p;
/* well, not exactly so for Linux, which does something inbetween, /* well, not exactly so for Linux, which does something inbetween,
* and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */ * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */
#else #else
/* discard the unrecognized conversion, just keep * /* discard the unrecognized conversion, just keep *
* the unrecognized conversion character */ * the unrecognized conversion character */
str_arg = p; str_arg_l = 0; str_arg = p; str_arg_l = 0;
#endif #endif
if (*p) str_arg_l++; /* include invalid conversion specifier unchanged if (*p) str_arg_l++; /* include invalid conversion specifier unchanged
if not at end-of-string */ if not at end-of-string */
break; break;
} }
if (*p) p++; /* step over the just processed conversion specifier */ if (*p) p++; /* step over the just processed conversion specifier */
/* insert padding to the left as requested by min_field_width; /* insert padding to the left as requested by min_field_width;
this does not include the zero padding in case of numerical conversions*/ this does not include the zero padding in case of numerical conversions*/
if (!justify_left) { /* left padding with blank or zero */ if (!justify_left) { /* left padding with blank or zero */
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
if (n > 0) { if (n > 0) {
if (str_l < str_m) { if (str_l < str_m) {
size_t avail = str_m-str_l; 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; str_l += n;
} }
} }
/* zero padding as requested by the precision or by the minimal field width /* zero padding as requested by the precision or by the minimal field width
* for numeric conversions required? */ * for numeric conversions required? */
if (number_of_zeros_to_pad <= 0) { if (number_of_zeros_to_pad <= 0) {
/* will not copy first part of numeric right now, * /* will not copy first part of numeric right now, *
* force it to be copied later in its entirety */ * force it to be copied later in its entirety */
zero_padding_insertion_ind = 0; zero_padding_insertion_ind = 0;
} else { } 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; int n = zero_padding_insertion_ind;
if (n > 0) { if (n > 0) {
if (str_l < str_m) { if (str_l < str_m) {
size_t avail = str_m-str_l; 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; 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; n = number_of_zeros_to_pad;
if (n > 0) { if (n > 0) {
if (str_l < str_m) { if (str_l < str_m) {
size_t avail = str_m-str_l; 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; str_l += n;
} }
} }
/* insert formatted string /* insert formatted string
* (or as-is conversion specifier for unknown conversions) */ * (or as-is conversion specifier for unknown conversions) */
{ int n = str_arg_l - zero_padding_insertion_ind; { int n = str_arg_l - zero_padding_insertion_ind;
if (n > 0) { if (n > 0) {
if (str_l < str_m) { if (str_l < str_m) {
size_t avail = str_m-str_l; size_t avail = str_m-str_l;
fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
(n>avail?avail:n)); (n>avail ? avail : n));
} }
str_l += n; str_l += n;
} }}
} /* insert right padding */
/* insert right padding */
if (justify_left) { /* right blank padding to the field width */ if (justify_left) { /* right blank padding to the field width */
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
if (n > 0) { if (n > 0) {
if (str_l < str_m) { if (str_l < str_m) {
size_t avail = str_m-str_l; 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; str_l += n;
} }
@ -829,7 +822,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
#endif #endif
#endif /* ndef HAVE_SNPRINTF */ #endif /* ndef HAVE_SNPRINTF */
/* /*
Local Variables: Local Variables:
tab-width: 3 tab-width: 3
end: end:
*/ */

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/** This module implements AARP, a necessary protocol for ELAP communication. **/ /** This module implements AARP, a necessary protocol for ELAP communication. **/
@ -24,10 +24,10 @@
struct amt_entry_t struct amt_entry_t
{ {
struct at_addr_t protocol; struct at_addr_t protocol;
struct ether_addr_t hardware; struct ether_addr_t hardware;
struct amt_entry_t* next; struct amt_entry_t* next;
}; };
typedef struct amt_entry_t* amt_t; typedef struct amt_entry_t* amt_t;
@ -38,253 +38,237 @@ static unsigned int retry_count;
static clock_t retry_timer; static clock_t retry_timer;
void aarp_init() void aarp_init() {
{ aarp_retry_reset();
aarp_retry_reset();
} }
void aarp_shutdown() void aarp_shutdown() {
{ struct amt_entry_t* entry = amt;
struct amt_entry_t* entry = amt; while (entry)
while (entry) {
{ struct amt_entry_t* next = entry->next;
struct amt_entry_t* next = entry->next; free(entry);
free(entry); entry = next;
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) 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)
if (source_at_addr && dest_at_addr && dest_hw_addr) {
{ struct aarp_header_t response;
struct aarp_header_t response; response.hardware_type = htons(AARP_HARDWARE_ETHER);
response.hardware_type = htons(AARP_HARDWARE_ETHER); response.protocol_type = htons(AARP_PROTOCOL_TYPE);
response.protocol_type = htons(AARP_PROTOCOL_TYPE); response.hw_addr_len = AARP_HW_ADDR_LEN;
response.hw_addr_len = AARP_HW_ADDR_LEN; response.protocol_addr_len = AARP_PROTOCOL_ADDR_LEN;
response.protocol_addr_len = AARP_PROTOCOL_ADDR_LEN; response.function = htons(function);
response.function = htons(function);
memcpy(&response.source_proto_addr.addr, source_at_addr, sizeof(response.source_proto_addr.addr)); 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.addr.network = htons(response.source_proto_addr.addr.network);
response.source_proto_addr.zero = 0x00; response.source_proto_addr.zero = 0x00;
memcpy(&response.dest_proto_addr.addr, dest_at_addr, sizeof(response.dest_proto_addr.addr)); 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.addr.network = htons(response.dest_proto_addr.addr.network);
response.dest_proto_addr.zero = 0x00; 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) if (dest_hw_addr == &HW_ZERO)
elap_send(&HW_APPLETALK_BROADCAST, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response); elap_send(&HW_APPLETALK_BROADCAST, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response);
else else
elap_send(&response.dest_hw_addr, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response); elap_send(&response.dest_hw_addr, &SNAP_AARP, sizeof(struct aarp_header_t), (byte*)&response);
} }
} }
void aarp_probe(const struct at_addr_t* addr) void aarp_probe(const struct at_addr_t* addr) {
{ if (addr)
if (addr) {
{ aarp_send_packet(AARP_FUNCTION_PROBE, addr, addr, &HW_ZERO);
aarp_send_packet(AARP_FUNCTION_PROBE, addr, addr, &HW_ZERO); }
}
} }
static void aarp_request(const struct at_addr_t* addr) static void aarp_request(const struct at_addr_t* addr) {
{ if (addr)
if (addr) {
{ aarp_send_packet(AARP_FUNCTION_REQUEST, atbridge_get_addr(), addr, &HW_ZERO);
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) static struct amt_entry_t* amt_lookup_entry_hardware(const struct ether_addr_t* hardware) {
{ if (hardware)
if (hardware) {
{ struct amt_entry_t* entry = amt;
struct amt_entry_t* entry = amt; while (entry)
while (entry) {
{ if (memcmp(&entry->hardware, hardware, sizeof(entry->hardware)) == 0)
if (memcmp(&entry->hardware, hardware, sizeof(entry->hardware)) == 0) return entry;
return entry; entry = entry->next;
entry = entry->next; }
} }
} return 0;
return 0;
} }
static struct amt_entry_t* amt_lookup_entry_protocol(const struct at_addr_t* protocol) static struct amt_entry_t* amt_lookup_entry_protocol(const struct at_addr_t* protocol) {
{ if (protocol)
if (protocol) {
{ struct amt_entry_t* entry = amt;
struct amt_entry_t* entry = amt; while (entry)
while (entry) {
{ if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0)
if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0) return entry;
return entry; entry = entry->next;
entry = entry->next; }
} }
} return 0;
return 0;
} }
static void amt_delete_entry_protocol(const struct at_addr_t* protocol) static void amt_delete_entry_protocol(const struct at_addr_t* protocol) {
{ if (protocol)
if (protocol) {
{ struct amt_entry_t* entry = amt;
struct amt_entry_t* entry = amt; struct amt_entry_t* previous = amt;
struct amt_entry_t* previous = amt; while (entry)
while (entry) {
{ if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0)
if (memcmp(&entry->protocol, protocol, sizeof(entry->protocol)) == 0) {
{ previous->next = entry->next;
previous->next = entry->next; free(entry);
free(entry); break;
break; }
} previous = entry;
previous = entry; entry = entry->next;
entry = entry->next; }
} }
}
} }
static void amt_add(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) 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.
// 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);
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol); if (entry)
if (entry) {
{ memcpy(&entry->hardware, hardware, sizeof(entry->hardware));
memcpy(&entry->hardware, hardware, sizeof(entry->hardware)); return;
return; }
}
entry = amt_lookup_entry_hardware(hardware); entry = amt_lookup_entry_hardware(hardware);
if (entry) if (entry)
{ {
memcpy(&entry->protocol, protocol, sizeof(entry->protocol)); memcpy(&entry->protocol, protocol, sizeof(entry->protocol));
return; return;
} }
// Otherwise, add a new entry. // Otherwise, add a new entry.
entry = (struct amt_entry_t*)malloc(sizeof(struct amt_entry_t)); entry = (struct amt_entry_t*)malloc(sizeof(struct amt_entry_t));
memcpy(&entry->hardware, hardware, sizeof(entry->hardware)); memcpy(&entry->hardware, hardware, sizeof(entry->hardware));
memcpy(&entry->protocol, protocol, sizeof(entry->protocol)); memcpy(&entry->protocol, protocol, sizeof(entry->protocol));
entry->next = amt; entry->next = amt;
amt = entry; amt = entry;
} }
const struct ether_addr_t* aarp_request_hardware(const struct at_addr_t* protocol) const struct ether_addr_t* aarp_request_hardware(const struct at_addr_t* protocol) {
{ struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol); if (entry)
if (entry) {
{ aarp_retry_reset();
aarp_retry_reset(); return (const struct ether_addr_t*)&entry->hardware;
return (const struct ether_addr_t*)&entry->hardware; }
} else
else {
{ // The AMT doesn't have this protocol address so issue a request at no more than the AARP_PROBE_INTERVAL period.
// 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)) &&
if (((clock() - retry_timer) >= (AARP_REQUEST_INTERVAL * CLOCKS_PER_SEC / 1000)) && (retry_count > 0))
(retry_count > 0)) {
{ aarp_request(protocol);
aarp_request(protocol);
retry_count--;
retry_timer = clock();
//atbridge_printf("AARP request count %d timer %d.\n", retry_count, retry_timer);
}
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) const struct at_addr_t* aarp_request_protocol(const struct ether_addr_t* hardware) {
{ struct amt_entry_t* entry = amt_lookup_entry_hardware(hardware);
struct amt_entry_t* entry = amt_lookup_entry_hardware(hardware); if (entry)
if (entry) return (const struct at_addr_t*)&entry->protocol;
return (const struct at_addr_t*)&entry->protocol; else
else return 0;
return 0;
} }
bool aarp_retry() bool aarp_retry() {
{ return retry_count > 0;
return retry_count > 0;
} }
void aarp_retry_reset() void aarp_retry_reset() {
{ retry_count = AARP_REQUEST_COUNT;
retry_count = AARP_REQUEST_COUNT; retry_timer = clock();
retry_timer = clock();
} }
void aarp_glean(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) void aarp_glean(const struct at_addr_t* protocol, const struct ether_addr_t* hardware) {
{ amt_add(protocol, hardware);
amt_add(protocol, hardware);
} }
bool aarp_address_used(const struct at_addr_t* protocol) bool aarp_address_used(const struct at_addr_t* protocol) {
{ // reference 2-8
// reference 2-8 if (protocol)
if (protocol) {
{ // Check for reserved node numbers, per reference 3-9.
// Check for reserved node numbers, per reference 3-9. if (protocol->node == 0x00 || protocol->node == 0xfe || protocol->node == 0xff)
if (protocol->node == 0x00 || protocol->node == 0xfe || protocol->node == 0xff) return true;
return true;
// Look for the address in the AMT. If it's there, another node is using this address. // 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); struct amt_entry_t* entry = amt_lookup_entry_protocol(protocol);
if (entry) if (entry)
return true; return true;
// Try a probe. If this address is in use, another node will reply with an AARP RESPONSE packet. // 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 // 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), // 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. // per the AARP protocol definition, before choosing this address.
aarp_probe(protocol); aarp_probe(protocol);
return false; return false;
} }
return false; return false;
} }
//// ////
void aarp_handle_packet(const struct aarp_header_t* aarp) void aarp_handle_packet(const struct aarp_header_t* aarp) {
{ if (aarp &&
if (aarp && aarp->hardware_type == AARP_HARDWARE_ETHER &&
aarp->hardware_type == AARP_HARDWARE_ETHER && aarp->protocol_type == AARP_PROTOCOL_TYPE &&
aarp->protocol_type == AARP_PROTOCOL_TYPE && aarp->hw_addr_len == AARP_HW_ADDR_LEN &&
aarp->hw_addr_len == AARP_HW_ADDR_LEN && aarp->protocol_addr_len == AARP_PROTOCOL_ADDR_LEN)
aarp->protocol_addr_len == AARP_PROTOCOL_ADDR_LEN) {
{ switch (aarp->function)
switch (aarp->function) {
{ case AARP_FUNCTION_REQUEST:
case AARP_FUNCTION_REQUEST: if (((aarp->dest_proto_addr.addr.network == atbridge_get_net()) ||
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.network == 0x00 /* reference 4-6 */)) && (aarp->dest_proto_addr.addr.node == atbridge_get_node()))
(aarp->dest_proto_addr.addr.node == atbridge_get_node())) {
{ // Generate a response for the AARP request.
// 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);
aarp_send_packet(AARP_FUNCTION_RESPONSE, &aarp->dest_proto_addr.addr, &aarp->source_proto_addr.addr, &aarp->source_hw_addr); }
} break;
break; case AARP_FUNCTION_RESPONSE:
case AARP_FUNCTION_RESPONSE: aarp_glean(&aarp->source_proto_addr.addr, &aarp->source_hw_addr);
aarp_glean(&aarp->source_proto_addr.addr, &aarp->source_hw_addr); aarp_glean(&aarp->dest_proto_addr.addr, &aarp->dest_hw_addr);
aarp_glean(&aarp->dest_proto_addr.addr, &aarp->dest_hw_addr); break;
break; case AARP_FUNCTION_PROBE:
case AARP_FUNCTION_PROBE: // AMT entry aging, method 2, reference 2-11
// AMT entry aging, method 2, reference 2-11 amt_delete_entry_protocol(&aarp->dest_proto_addr.addr);
amt_delete_entry_protocol(&aarp->dest_proto_addr.addr); break;
break; default:
default: break;
break; }
} }
}
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) 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. **/ /** 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(); static void send_rtmp_request();
bool atbridge_init() 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 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)
if (local_address.network == 0) {
{ // Obtain a provisional node address and startup range network.
// 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.
// 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.
// The bridge should follow the complicated process on page 4-9 to obtain the network and node number. srand((unsigned int)time(0));
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.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);
local_address.node = (at_node_t)((double)rand()/RAND_MAX + (NODE_STARTUP_HIGH - NODE_STARTUP_LOW) + 0x01);
aarp_init(); aarp_init();
llap_init(); llap_init();
if (!elap_init()) if (!elap_init())
{ {
atbridge_shutdown(); atbridge_shutdown();
return false; return false;
} }
} }
return true; return true;
} }
void atbridge_shutdown() void atbridge_shutdown() {
{ llap_shutdown();
llap_shutdown(); elap_shutdown();
elap_shutdown(); aarp_shutdown();
aarp_shutdown();
} }
void atbridge_set_diagnostics(bool enabled) void atbridge_set_diagnostics(bool enabled) {
{ diagnostics = enabled;
diagnostics = enabled;
} }
bool atbridge_get_diagnostics() bool atbridge_get_diagnostics() {
{ return diagnostics;
return diagnostics;
} }
void atbridge_printf(const char *fmt, ...) void atbridge_printf(const char *fmt, ...) {
{ if (atbridge_get_diagnostics())
if (atbridge_get_diagnostics()) {
{ va_list args;
va_list args; va_start(args, fmt);
va_start(args, fmt); vprintf(fmt, args);
vprintf(fmt, args); va_end(args);
va_end(args); }
}
} }
const struct at_addr_t* atbridge_get_addr() const struct at_addr_t* atbridge_get_addr() {
{ return &local_address;
return &local_address;
} }
const at_network_t atbridge_get_net() const at_network_t atbridge_get_net() {
{ return local_address.network;
return local_address.network;
} }
const at_node_t atbridge_get_node() const at_node_t atbridge_get_node() {
{ return local_address.node;
return local_address.node;
} }
void atbridge_set_net(at_network_t net) void atbridge_set_net(at_network_t net) {
{ local_address.network = net;
local_address.network = net;
} }
void atbridge_set_node(at_node_t node) void atbridge_set_node(at_node_t node) {
{ local_address.node = node;
local_address.node = node;
} }
bool atbridge_address_used(const struct at_addr_t* addr) bool atbridge_address_used(const struct at_addr_t* addr) {
{ if (!sent_rtmp_request)
if (!sent_rtmp_request) send_rtmp_request();
send_rtmp_request(); return aarp_address_used(addr);
return aarp_address_used(addr);
} }
/* Calculate a DDP checksum, per Apple's documented algorithm in 4-17 of "Inside AppleTalk". */ /* Calculate a DDP checksum, per Apple's documented algorithm in 4-17 of "Inside AppleTalk". */
static word16 get_checksum(size_t size, byte data[]) static word16 get_checksum(size_t size, byte data[]) {
{ word16 cksum = 0;
word16 cksum = 0; for (unsigned int i = 0; i < size; i++)
for (unsigned int i = 0; i < size; i++) {
{ cksum += data[i];
cksum += data[i]; cksum = (cksum << 1) | ((cksum & 0x8000) >> 15); // roll left
cksum = (cksum << 1) | ((cksum & 0x8000) >> 15); // roll left }
} if (cksum == 0)
if (cksum == 0) cksum = 0xffff;
cksum = 0xffff; return cksum;
return cksum;
} }
static void calculate_checksum(struct packet_t* packet) static void calculate_checksum(struct packet_t* packet) {
{ if (packet && packet->data && (packet->size >= sizeof(struct DDP_LONG)) && (packet->type == LAP_DDP_LONG))
if (packet && packet->data && (packet->size >= sizeof(struct DDP_LONG)) && (packet->type == LAP_DDP_LONG)) {
{ struct DDP_LONG* header = (struct DDP_LONG*)(packet->data);
struct DDP_LONG* header = (struct DDP_LONG*)(packet->data); header->checksum = htons(get_checksum(
header->checksum = htons(get_checksum( packet->size - offsetof(struct DDP_LONG, dest_net),
packet->size - offsetof(struct DDP_LONG, dest_net), (byte*)&header->dest_net));
(byte*)&header->dest_net)); }
}
} }
/* Convert a long-form DDP header to a short-form header. This function only converts the headers. */ /* 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) static word16 convert_ddp_header_to_short(const struct DDP_LONG* in, struct DDP_SHORT* out) {
{ word16 size;
word16 size;
if (!in || !out) if (!in || !out)
return 0; 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; size = ((in->length[0] & 0x3) << 8) + (in->length[1]) - (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
out->length[1] = size & 0xff;
out->dest_socket = in->dest_socket; out->length[0] = (size >> 8) & 0x03;
out->source_socket = in->source_socket; out->length[1] = size & 0xff;
out->type = in->type;
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. */ /* 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. */ /* 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) 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;
word16 size;
if (!in || !out) if (!in || !out)
return 0; 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 (source.network) size = ((in->length[0] & 0x3) << 8) + (in->length[1]) + (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
out->source_net = source.network; out->length[0] = (size >> 8) & 0x03;
else out->length[1] = size & 0xff;
out->source_net = atbridge_get_net();
out->source_net = (at_network_t)htons(out->source_net);
out->dest_node = dest.node; out->checksum = 0x0000; /* 0x0000 == no checksum calculated, reference 4-17 */
out->source_node = source.node;
out->dest_socket = in->dest_socket; if (dest.network)
out->source_socket = in->source_socket; 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. */ /* Convert a short-form DDP packet to a long-form packet. */
/* This function converts an entire packet, not just the header. */ /* This function converts an entire packet, not just the header. */
static void convert_ddp_packet_to_long(struct packet_t* packet) 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)))
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;
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
const size_t payload_size = packet->size - sizeof(struct DDP_SHORT); const size_t payload_size = packet->size - sizeof(struct DDP_SHORT);
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_LONG)); byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_LONG));
struct DDP_LONG* header_long = (struct DDP_LONG*)data; 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); 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->dest.network = ntohs(header_long->dest_net);
packet->source.network = ntohs(header_long->source_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->type = LAP_DDP_LONG;
packet->size = size; packet->size = size;
// Replace the original short-form packet data. // Replace the original short-form packet data.
free(packet->data); free(packet->data);
packet->data = data; packet->data = data;
calculate_checksum(packet); calculate_checksum(packet);
} }
} }
/* Convert a long-form DDP packet to short-form. */ /* Convert a long-form DDP packet to short-form. */
static void convert_ddp_packet_to_short(struct packet_t* packet) static void convert_ddp_packet_to_short(struct packet_t* packet) {
{ if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
if (packet && (packet->type == LAP_DDP_LONG) && packet->data) {
{ struct DDP_LONG* header_long = (struct 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); const size_t payload_size = packet->size - sizeof(struct DDP_LONG);
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_SHORT)); byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_SHORT));
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data; 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->type = LAP_DDP_SHORT;
packet->size = size; packet->size = size;
free(packet->data); free(packet->data);
packet->data = data; packet->data = data;
} }
} }
/*static void convert_rtmp_to_extended(struct packet_t* packet) /*static void convert_rtmp_to_extended(struct packet_t* packet)
{ {
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data) if (packet && (packet->type == LAP_DDP_SHORT) && packet->data)
{ {
struct DDP_SHORT* header_short = (struct 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) if (header_short->type != DDP_TYPE_RTMP || header_short->dest_socket != DDP_SOCKET_RTMP)
return; 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. // Construct a new long-form DDP packet header.
size_t size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_extended_data_t); size_t size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_extended_data_t);
byte* data = (byte*)malloc(size); byte* data = (byte*)malloc(size);
struct DDP_LONG* header_long = (struct DDP_LONG*)data; struct DDP_LONG* header_long = (struct DDP_LONG*)data;
convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long); 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;
// Copy the routing tuples. struct rtmp_extended_data_t* out = (struct rtmp_extended_data_t*)(data + sizeof(struct DDP_LONG));
struct rtmp_nonextended_tuple_t* in_tuple = (struct rtmp_nonextended_tuple_t*)(packet->data + sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_data_t)); out->net = in->net;
struct rtmp_extended_tuple_t* out_tuple = (struct rtmp_extended_tuple_t*)(data + size); out->id_length = in->id_length;
while ((byte*)in_tuple < (packet->data + packet->size)) out->node = in->node;
{
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++;
}
free(packet->data); // Copy the routing tuples.
packet->data = data; struct rtmp_nonextended_tuple_t* in_tuple = (struct rtmp_nonextended_tuple_t*)(packet->data + sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_data_t));
packet->size = size; struct rtmp_extended_tuple_t* out_tuple = (struct rtmp_extended_tuple_t*)(data + size);
packet->type = LAP_DDP_LONG; 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) free(packet->data);
{ packet->data = data;
if (packet && (packet->type == LAP_DDP_LONG) && packet->data) packet->size = size;
{ packet->type = LAP_DDP_LONG;
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)); 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); struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
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_nonextended_response_t* out = (struct rtmp_nonextended_response_t*)(data + sizeof(struct DDP_SHORT)); size_t size = sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_response_t);
out->net = in->net; byte* data = (byte*)malloc(size);
out->id_length = in->id_length; struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
out->node = in->node; 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)); struct rtmp_nonextended_response_t* out = (struct rtmp_nonextended_response_t*)(data + sizeof(struct DDP_SHORT));
rtmp_nonextended_tuple_t* out_tuple = (rtmp_nonextended_tuple_t*)(data + size); out->net = in->net;
while ((byte*)in_tuple < (packet->data + packet->size)) out->id_length = in->id_length;
{ out->node = in->node;
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); /*rtmp_extended_tuple_t* in_tuple = (rtmp_extended_tuple_t*)(packet->data + sizeof(DDP_LONG) + sizeof(rtmp_extended_data_t));
packet->data = data; rtmp_nonextended_tuple_t* out_tuple = (rtmp_nonextended_tuple_t*)(data + size);
packet->size = size; while ((byte*)in_tuple < (packet->data + packet->size))
packet->type = LAP_DDP_SHORT; {
} 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. */ /* Learn our network number from RTMP packets. */
/* "Inside AppleTalk", section 4-8, describes this approach for non-extended networks. /* "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), 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. */ but the easy approach using RTMP seems adequate for now. */
static void glean_net_from_rtmp(struct packet_t* packet) static void glean_net_from_rtmp(struct packet_t* packet) {
{ if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
if (packet && (packet->type == LAP_DDP_LONG) && packet->data) {
{ struct DDP_LONG* header_long = (struct 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)
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP) return;
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() static void send_rtmp_request() {
{ struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
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);
struct DDP_LONG* header = (struct DDP_LONG*)packet->data; packet->type = LAP_DDP_LONG;
header->type = DDP_TYPE_RTMP_REQUEST; packet->dest.network = atbridge_get_net();
header->source_net = htons(packet->source.network); packet->dest.node = 255;
header->source_node = packet->source.node; packet->source.network = atbridge_get_net();
header->source_socket = DDP_SOCKET_RTMP; packet->source.node = atbridge_get_node();
header->dest_net = htons(packet->dest.network); packet->next = 0;
header->dest_node = packet->dest.node; packet->size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_request_t);
header->dest_socket = DDP_SOCKET_RTMP; packet->data = (byte*)malloc(packet->size);
header->length[0] = (packet->size >> 8) & 0x03;
header->length[1] = packet->size & 0xff;
struct rtmp_request_t* request = (struct rtmp_request_t*)(packet->data + sizeof(struct DDP_LONG)); struct DDP_LONG* header = (struct DDP_LONG*)packet->data;
request->function = RTMP_FUNCTION_REQUEST; 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); struct rtmp_request_t* request = (struct rtmp_request_t*)(packet->data + sizeof(struct DDP_LONG));
request->function = RTMP_FUNCTION_REQUEST;
elap_enqueue_out(packet);
sent_rtmp_request = true; calculate_checksum(packet);
elap_enqueue_out(packet);
sent_rtmp_request = true;
} }
void atbridge_process() void atbridge_process() {
{ elap_process();
elap_process(); //llap_process();
//llap_process();
struct packet_t* packet = elap_dequeue_in();
struct packet_t* packet = elap_dequeue_in(); if (packet)
if (packet) {
{ glean_net_from_rtmp(packet);
glean_net_from_rtmp(packet); convert_rtmp_to_nonextended(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).
// 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);
convert_ddp_packet_to_short(packet); llap_enqueue_out(packet);
llap_enqueue_out(packet); }
} packet = llap_dequeue_in();
packet = llap_dequeue_in(); if (packet)
if (packet) {
{ // ELAP does not support short-form DDP, so convert such packets to long-form.
// ELAP does not support short-form DDP, so convert such packets to long-form. convert_ddp_packet_to_long(packet);
convert_ddp_packet_to_long(packet); elap_enqueue_out(packet);
elap_enqueue_out(packet); }
}
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/** This module implements the ELAP port of the bridge. **/ /** 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 struct ether_addr_t HW_LOCAL;
/*static void dump_device_list(pcap_if_t* devices) /*static void dump_device_list(pcap_if_t* devices)
{ {
int i = 0; int i = 0;
for(pcap_if_t* device = devices; device; device = device->next) for(pcap_if_t* device = devices; device; device = device->next)
{ {
printf("%d. %s", ++i, device->name); printf("%d. %s", ++i, device->name);
if (device->description) if (device->description)
printf(" (%s)\n", device->description); printf(" (%s)\n", device->description);
else else
printf(" (No description available)\n"); printf(" (No description available)\n");
} }
}*/ }*/
static void elap_clone_host_mac(pcap_if_t* device) static void elap_clone_host_mac(pcap_if_t* device) {
{ if (!device)
if (!device) return;
return;
#ifdef WIN32 #ifdef WIN32
//// ////
// Extract the device GUID, which Windows uses to identify the device. // Extract the device GUID, which Windows uses to identify the device.
char* name = device->name; char* name = device->name;
while (name && *name != '{') while (name && *name != '{')
name++; name++;
size_t guidLen = strlen(name); size_t guidLen = strlen(name);
//// ////
// Find and copy the device MAC address. // Find and copy the device MAC address.
ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 15; ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 15;
IP_ADAPTER_ADDRESSES* addresses = malloc(size); 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);
}
if (result == NO_ERROR) ULONG result = GetAdaptersAddresses(AF_UNSPEC,
{ GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
// 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); 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 #else
#ifdef AF_PACKET #ifdef AF_PACKET
struct pcap_addr* address; struct pcap_addr* address;
for (address = device->addresses; address != 0; address = address->next) for (address = device->addresses; address != 0; address = address->next)
if (address->addr->sa_family == AF_PACKET) if (address->addr->sa_family == AF_PACKET)
{ {
struct sockaddr_ll* ll = (struct sockaddr_ll*)address->addr; struct sockaddr_ll* ll = (struct sockaddr_ll*)address->addr;
memcpy(&HW_LOCAL.mac, ll->sll_addr, sizeof(HW_LOCAL.mac)); memcpy(&HW_LOCAL.mac, ll->sll_addr, sizeof(HW_LOCAL.mac));
} }
#endif #endif
#endif #endif
} }
const struct ether_addr_t* elap_get_mac() const struct ether_addr_t* elap_get_mac() {
{ return &HW_LOCAL;
return &HW_LOCAL;
} }
bool elap_init() bool elap_init() {
{ port_init(&elap_port);
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* device;
pcap_if_t* alldevs; pcap_if_t* alldevs;
int i = 0; int i = 0;
char errbuf[PCAP_ERRBUF_SIZE];
// Load the PCAP library.
if (!pcapdelay_load())
{
halt_printf("ATBridge: PCAP not available.\n");
return false;
}
// Retrieve the device list. char errbuf[PCAP_ERRBUF_SIZE];
if(pcapdelay_findalldevs(&alldevs, errbuf) == -1)
{
atbridge_printf("ATBridge: Error enumerating PCAP devices: %s\n", errbuf);
return false;
}
//dump_device_list(alldevs);
// Jump to the selected adapter. // Load the PCAP library.
for (device = alldevs, i = 0; i < g_ethernet_interface; device = device->next, i++); if (!pcapdelay_load())
if (!device) {
{ halt_printf("ATBridge: PCAP not available.\n");
halt_printf("ATBridge: PCAP device not found. Check interface number in settings.\n"); return false;
return false; }
}
// Clone the MAC address of the underlying interface. In certain configurations (e.g. Windows with an MS Loopback // Retrieve the device list.
// interface), the interface, even in promiscous mode, filters foreign MAC addresses. if(pcapdelay_findalldevs(&alldevs, errbuf) == -1)
elap_clone_host_mac(device); {
atbridge_printf("ATBridge: Error enumerating PCAP devices: %s\n", errbuf);
return false;
}
//dump_device_list(alldevs);
// Open the adapter, // Jump to the selected adapter.
if ((pcap_session = pcapdelay_open_live(device->name, // name of the device for (device = alldevs, i = 0; i < g_ethernet_interface; device = device->next, i++);
65536, // portion of the packet to capture. if (!device)
// 65536 grants that the whole packet will be captured on all the MACs. {
1, // promiscuous mode (nonzero means promiscuous) halt_printf("ATBridge: PCAP device not found. Check interface number in settings.\n");
1, // read timeout return false;
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. // Clone the MAC address of the underlying interface. In certain configurations (e.g. Windows with an MS Loopback
if (pcapdelay_datalink(pcap_session) == DLT_EN10MB) // interface), the interface, even in promiscous mode, filters foreign MAC addresses.
{ elap_clone_host_mac(device);
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", // Open the adapter,
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]); if ((pcap_session = pcapdelay_open_live(device->name, // name of the device
65536, // portion of the packet to capture.
pcapdelay_freealldevs(alldevs); // 65536 grants that the whole packet will be captured on all the MACs.
return true; 1, // promiscuous mode (nonzero means promiscuous)
} 1, // read timeout
else errbuf // error buffer
{ )) == NULL)
pcapdelay_close(pcap_session); {
pcap_session = 0; halt_printf("ATBridge: Unable to open the adapter. Pcap does not support %s.\n", device->name);
halt_printf("ATBridge: Selected network device %s must support Ethernet.\n", device->description); pcapdelay_freealldevs(alldevs);
pcapdelay_freealldevs(alldevs); return false;
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() void elap_shutdown() {
{ port_shutdown(&elap_port);
port_shutdown(&elap_port); if (pcap_session)
if (pcap_session) {
{ pcapdelay_close(pcap_session);
pcapdelay_close(pcap_session); pcap_session = 0;
pcap_session = 0; }
} pcapdelay_unload();
pcapdelay_unload();
} }
void elap_enqueue_out(struct packet_t* packet) void elap_enqueue_out(struct packet_t* packet) {
{ enqueue_packet(&elap_port.out, packet);
enqueue_packet(&elap_port.out, packet);
} }
struct packet_t* elap_dequeue_in() struct packet_t* elap_dequeue_in() {
{ return dequeue(&elap_port.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[]) 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)
if (pcap_session && dest && discriminator) {
{ // Allocate heap space for the frame.
// Allocate heap space for the frame. const size_t frame_size = sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t) + size;
const size_t frame_size = sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t) + size; u_char* frame_data;
u_char* frame_data; size_t pad = 0;
size_t pad = 0; if (frame_size < ETHER_MIN_SIZE)
if (frame_size < ETHER_MIN_SIZE) pad = ETHER_MIN_SIZE - frame_size;
pad = ETHER_MIN_SIZE - frame_size; frame_data = (u_char*)malloc(frame_size + pad);
frame_data = (u_char*)malloc(frame_size + pad);
// Build the 802.3 header. // Build the 802.3 header.
struct ethernet_header_t* ether = (struct ethernet_header_t*)frame_data; struct ethernet_header_t* ether = (struct ethernet_header_t*)frame_data;
memcpy(ether->dest.mac, dest, sizeof(ether->dest.mac)); memcpy(ether->dest.mac, dest, sizeof(ether->dest.mac));
memcpy(ether->source.mac, HW_LOCAL.mac, sizeof(ether->source.mac)); memcpy(ether->source.mac, HW_LOCAL.mac, sizeof(ether->source.mac));
ether->length = htons(frame_size - sizeof(struct ethernet_header_t)); ether->length = htons(frame_size - sizeof(struct ethernet_header_t));
// Build the 802.2 header. // Build the 802.2 header.
struct snap_header_t* snap = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t)); struct snap_header_t* snap = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t));
snap->dsap = SNAP_DSAP; snap->dsap = SNAP_DSAP;
snap->ssap = SNAP_SSAP; snap->ssap = SNAP_SSAP;
snap->control = SNAP_CONTROL; snap->control = SNAP_CONTROL;
memcpy(&snap->discriminator, discriminator, sizeof(snap->discriminator)); memcpy(&snap->discriminator, discriminator, sizeof(snap->discriminator));
// Add the data payload. // 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)); 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); memcpy(payload, data, size);
// Add padding to meet minimum Ethernet frame size. // Add padding to meet minimum Ethernet frame size.
if (pad > 0) if (pad > 0)
memset(frame_data + frame_size, 0, pad); 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() static bool elap_send_one_queued() {
{ // Attempt to send one packet out the host network interface.
// Attempt to send one packet out the host network interface. struct packet_t* packet = queue_peek(&elap_port.out);
struct packet_t* packet = queue_peek(&elap_port.out); if (packet)
if (packet) {
{ // Find the MAC address.
// Find the MAC address. const struct ether_addr_t* dest;
const struct ether_addr_t* dest; if (packet->dest.node == at_broadcast_node)
if (packet->dest.node == at_broadcast_node) dest = &HW_APPLETALK_BROADCAST;
dest = &HW_APPLETALK_BROADCAST; else
else dest = aarp_request_hardware(&packet->dest);
dest = aarp_request_hardware(&packet->dest);
// Send it. // Send it.
if (dest) if (dest)
{ {
elap_send(dest, &SNAP_APPLETALK, packet->size, packet->data); elap_send(dest, &SNAP_APPLETALK, packet->size, packet->data);
dequeue(&elap_port.out); dequeue(&elap_port.out);
free(packet->data); free(packet->data);
free(packet); free(packet);
} }
else else
{ {
// AARP does not have the needed hardware address. Give AARP time to obtain the address and keep the current packet. // AARP does not have the needed hardware address. Give AARP time to obtain the address and keep the current packet.
if (!aarp_retry()) if (!aarp_retry())
{ {
// However, if AARP has reached the retry limit, the packet is undeliverable. Discard the packet and move on. // 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); 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(); aarp_retry_reset();
dequeue(&elap_port.out); dequeue(&elap_port.out);
free(packet->data); free(packet->data);
free(packet); free(packet);
} }
} }
return true; return true;
} }
else else
return false; return false;
} }
static void elap_send_all_queued() static void elap_send_all_queued() {
{ while (elap_send_one_queued());
while (elap_send_one_queued());
} }
static bool elap_receive_one() static bool elap_receive_one() {
{ if (!pcap_session)
if (!pcap_session) return false;
return false;
struct pcap_pkthdr header; struct pcap_pkthdr header;
const u_char* packet = pcapdelay_next(pcap_session, &header); const u_char* packet = pcapdelay_next(pcap_session, &header);
if (packet) if (packet)
{ {
// Receive and process one packet from the host network interface. // Receive and process one packet from the host network interface.
//// ////
// Check the Ethernet 802.3 header. // Check the Ethernet 802.3 header.
const struct ethernet_header_t* ether = (struct ethernet_header_t*)packet; const struct ethernet_header_t* ether = (struct ethernet_header_t*)packet;
if (header.len > sizeof(struct ethernet_header_t) && if (header.len > sizeof(struct ethernet_header_t) &&
ntohs(ether->length) <= ETHER_MAX_SIZE && ntohs(ether->length) <= ETHER_MAX_SIZE &&
ntohs(ether->length) > sizeof(struct snap_header_t) && 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->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_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
memcmp(&ether->dest, &HW_APPLETALK_BROADCAST, sizeof(ether->dest)) == 0 /* ... or for broadcast. */) memcmp(&ether->dest, &HW_APPLETALK_BROADCAST, sizeof(ether->dest)) == 0 /* ... or for broadcast. */)
) )
{ {
// Check the 802.2 SNAP header. // Check the 802.2 SNAP header.
const struct snap_header_t* snap = (struct snap_header_t*)(packet + sizeof(struct ethernet_header_t)); const struct snap_header_t* snap = (struct snap_header_t*)(packet + sizeof(struct ethernet_header_t));
if (snap->dsap == SNAP_DSAP && if (snap->dsap == SNAP_DSAP &&
snap->ssap == SNAP_SSAP && snap->ssap == SNAP_SSAP &&
snap->control == SNAP_CONTROL) snap->control == SNAP_CONTROL)
{ {
if (memcmp(&snap->discriminator, &SNAP_APPLETALK, sizeof(snap->discriminator)) == 0) if (memcmp(&snap->discriminator, &SNAP_APPLETALK, sizeof(snap->discriminator)) == 0)
{ {
// Handle an AppleTalk packet. // Handle an AppleTalk packet.
const size_t payload_size = ntohs(ether->length) - sizeof(struct snap_header_t); 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); const u_char* payload = packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t);
byte* copy = (byte*)malloc(payload_size); byte* copy = (byte*)malloc(payload_size);
memcpy(copy, payload, payload_size); memcpy(copy, payload, payload_size);
// ELAP does not support short-form DDP, so this must be a long-form DDP packet. // ELAP does not support short-form DDP, so this must be a long-form DDP packet.
struct at_addr_t source, dest; struct at_addr_t source, dest;
if (payload_size >= sizeof(struct DDP_LONG)) if (payload_size >= sizeof(struct DDP_LONG))
{ {
// Extract the protocol address from the header. // Extract the protocol address from the header.
// //
// ELAP really shouldn't be looking at the header for the next level of the protocol stack, // 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 // but this is a convenient place to glean addresses for the AMT, a process that needs both
// hardware and protocol addresses. // hardware and protocol addresses.
struct DDP_LONG* header = (struct DDP_LONG*)copy; struct DDP_LONG* header = (struct DDP_LONG*)copy;
dest.network = (at_network_t)ntohs(header->dest_net); dest.network = (at_network_t)ntohs(header->dest_net);
source.network = (at_network_t)ntohs(header->source_net); source.network = (at_network_t)ntohs(header->source_net);
dest.node = header->dest_node; dest.node = header->dest_node;
source.node = header->source_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); aarp_glean(&source, &ether->source);
} }
else else
atbridge_printf("ATBridge: Dropping invalid short ELAP frame.\n"); atbridge_printf("ATBridge: Dropping invalid short ELAP frame.\n");
} }
else if (memcmp(&snap->discriminator, &SNAP_AARP, sizeof(snap->discriminator)) == 0) else if (memcmp(&snap->discriminator, &SNAP_AARP, sizeof(snap->discriminator)) == 0)
{ {
// Handle an AARP packet. // Handle an AARP packet.
struct aarp_header_t* aarp = (struct aarp_header_t*)(packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t)); 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->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->source_proto_addr.addr.network = ntohs(aarp->source_proto_addr.addr.network);
aarp->function = ntohs(aarp->function); aarp->function = ntohs(aarp->function);
aarp->hardware_type = ntohs(aarp->hardware_type); aarp->hardware_type = ntohs(aarp->hardware_type);
aarp->protocol_type = ntohs(aarp->protocol_type); aarp->protocol_type = ntohs(aarp->protocol_type);
aarp_handle_packet(aarp); aarp_handle_packet(aarp);
} }
} }
} }
return true; return true;
} }
else else
return false; return false;
} }
static void elap_receive_all() static void elap_receive_all() {
{ while (elap_receive_one());
while (elap_receive_one());
} }
void elap_process() void elap_process() {
{ elap_receive_all();
elap_receive_all(); elap_send_all_queued();
elap_send_all_queued();
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/** This module implements the LLAP port of the bridge. **/ /** This module implements the LLAP port of the bridge. **/
@ -14,12 +14,12 @@
#include "llap.h" #include "llap.h"
typedef enum { typedef enum {
LLAP_DDP_SHORT = 0x01, LLAP_DDP_SHORT = 0x01,
LLAP_DDP_LONG = 0x02, LLAP_DDP_LONG = 0x02,
LLAP_ENQ = 0x81, LLAP_ENQ = 0x81,
LLAP_ACK = 0x82, LLAP_ACK = 0x82,
LLAP_RTS = 0x84, LLAP_RTS = 0x84,
LLAP_CTS = 0x85 LLAP_CTS = 0x85
} LLAP_TYPES; } LLAP_TYPES;
const unsigned int LLAP_PACKET_MAX = 603 /* bytes */; 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; static struct packet_port_t llap_port;
typedef enum { typedef enum {
DIALOG_READY, DIALOG_READY,
DIALOG_GOT_CTS, DIALOG_GOT_CTS,
DIALOG_WAIT_IDG DIALOG_WAIT_IDG
} DIALOG_STATE; } DIALOG_STATE;
static DIALOG_STATE dialog_state; static DIALOG_STATE dialog_state;
static double dialog_end_dcycs; static double dialog_end_dcycs;
static double last_frame_dcycs; static double last_frame_dcycs;
void llap_init() void llap_init() {
{ dialog_state = DIALOG_READY;
dialog_state = DIALOG_READY; last_frame_dcycs = 0;
last_frame_dcycs = 0; port_init(&llap_port);
port_init(&llap_port);
} }
void llap_shutdown() void llap_shutdown() {
{ port_shutdown(&llap_port);
port_shutdown(&llap_port);
} }
/** Queue one data packet out from the bridge's LLAP port and into the guest. **/ /** Queue one data packet out from the bridge's LLAP port and into the guest. **/
void llap_enqueue_out(struct packet_t* packet) void llap_enqueue_out(struct packet_t* packet) {
{ // Generate the RTS.
// Generate the RTS. struct packet_t* rts = (struct packet_t*)malloc(sizeof(struct packet_t));
struct packet_t* rts = (struct packet_t*)malloc(sizeof(struct packet_t)); rts->source.network = packet->source.network;
rts->source.network = packet->source.network; rts->source.node = packet->source.node;
rts->source.node = packet->source.node; rts->dest.network = packet->dest.network;
rts->dest.network = packet->dest.network; rts->dest.node = packet->dest.node;
rts->dest.node = packet->dest.node; rts->size = 0;
rts->size = 0; rts->data = 0;
rts->data = 0; rts->type = LLAP_RTS;
rts->type = LLAP_RTS; enqueue_packet(&llap_port.out, rts);
enqueue_packet(&llap_port.out, rts);
// Enqueue the data. // Enqueue the data.
enqueue_packet(&llap_port.out, packet); enqueue_packet(&llap_port.out, packet);
} }
struct packet_t* llap_dequeue_in() struct packet_t* llap_dequeue_in() {
{ return dequeue(&llap_port.in);
return dequeue(&llap_port.in);
} }
static void llap_dump_packet(size_t size, byte data[]) static void llap_dump_packet(size_t size, byte data[]) {
{ if (size < LLAP_PACKET_MIN)
if (size < LLAP_PACKET_MIN) atbridge_printf("LLAP short packet.\n");
atbridge_printf("LLAP short packet.\n"); else if (size > LLAP_PACKET_MAX)
else if (size > LLAP_PACKET_MAX) atbridge_printf("LLAP long packet.\n");
atbridge_printf("LLAP long packet.\n"); else
else {
{ at_node_t dest = data[0];
at_node_t dest = data[0]; at_node_t source = data[1];
at_node_t source = data[1]; LLAP_TYPES type = (LLAP_TYPES)(data[2]);
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;
}
if (typeName) const char* typeName = 0;
atbridge_printf("LLAP[%d->%d] %s: %d bytes.\n", source, dest, typeName, size); switch (type)
else {
atbridge_printf("LLAP[%d->%d] %x: %d bytes.\n", source, dest, type, size); case LLAP_DDP_SHORT:
typeName = "DDP (short)";
/*for (size_t i = 0; i < size; i++) break;
atbridge_printf("%02x ", data[i]); case LLAP_DDP_LONG:
atbridge_printf("\n");*/ 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 **/ /** Reply to a control packet from the GS **/
static void llap_reply_control(at_node_t dest, at_node_t source, LLAP_TYPES type) 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 dest_addr = { 0, dest }; struct at_addr_t source_addr = { 0, source };
struct at_addr_t source_addr = { 0, source };
// Insert control packets at the head of the queue contrary to normal FIFO queue operation // 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. // to ensure that control frames arrive in the intended order.
insert(&llap_port.out, dest_addr, source_addr, type, 0, 0); insert(&llap_port.out, dest_addr, source_addr, type, 0, 0);
} }
/** Accept a data packet from the GS. **/ /** Accept a data packet from the GS. **/
static void llap_handle_data(size_t size, byte data[]) static void llap_handle_data(size_t size, byte data[]) {
{ at_node_t dest = data[0];
at_node_t dest = data[0]; at_node_t source = data[1];
at_node_t source = data[1]; LLAP_TYPES type = (LLAP_TYPES)(data[2]);
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
const size_t data_size = size - 3; const size_t data_size = size - 3;
byte* data_copy = (byte*)malloc(data_size); byte* data_copy = (byte*)malloc(data_size);
memcpy(data_copy, data + 3, data_size); memcpy(data_copy, data + 3, data_size);
struct at_addr_t dest_addr = { 0, dest }; struct at_addr_t dest_addr = { 0, dest };
struct at_addr_t source_addr = { 0, source }; struct at_addr_t source_addr = { 0, source };
enqueue(&llap_port.in, dest_addr, source_addr, type, data_size, data_copy); enqueue(&llap_port.in, dest_addr, source_addr, type, data_size, data_copy);
} }
/** Accept a control packet from the GS. **/ /** Accept a control packet from the GS. **/
static void llap_handle_control(size_t size, byte data[]) static void llap_handle_control(size_t size, byte data[]) {
{ at_node_t dest = data[0];
at_node_t dest = data[0]; at_node_t source = data[1];
at_node_t source = data[1]; LLAP_TYPES type = (LLAP_TYPES)(data[2]);
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) switch (type)
{ {
case LLAP_ENQ: case LLAP_ENQ:
// Require the GS to take a valid "client" address not known to be in use. // Require the GS to take a valid "client" address not known to be in use.
if (dest > 127 || dest == 0 || atbridge_address_used(&addr)) if (dest > 127 || dest == 0 || atbridge_address_used(&addr))
llap_reply_control(source, dest, LLAP_ACK); llap_reply_control(source, dest, LLAP_ACK);
break; break;
case LLAP_ACK: case LLAP_ACK:
break; break;
case LLAP_RTS: case LLAP_RTS:
if (dest != at_broadcast_node) if (dest != at_broadcast_node)
// The GS is trying to make a directed transmission. Provide the required RTS/CTS handshake. // The GS is trying to make a directed transmission. Provide the required RTS/CTS handshake.
// Note that broadcast packets do not require a CTS. // Note that broadcast packets do not require a CTS.
llap_reply_control(source, dest, LLAP_CTS); llap_reply_control(source, dest, LLAP_CTS);
break; break;
case LLAP_CTS: case LLAP_CTS:
// The GS sent a CTS. If the bridge has pending data, prepare to deliver the packet. // The GS sent a CTS. If the bridge has pending data, prepare to deliver the packet.
dialog_state = DIALOG_GOT_CTS; dialog_state = DIALOG_GOT_CTS;
break; break;
default: default:
break; break;
} }
} }
/** Occassionally, we receive an invalid packet from the GS. I'm unsure if this is due to a bug in GS/OS /** 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 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. current, corrupted dialog. Link errors are routine in real LocalTalk networks, and LocalTalk will recover.
**/ **/
static void llap_reset_dialog() static void llap_reset_dialog() {
{ dialog_state = DIALOG_READY;
dialog_state = DIALOG_READY; last_frame_dcycs = 0;
last_frame_dcycs = 0;
// Discard packets until the queue is either empty or the next dialog starts (and dialogs begin with an RTS). // Discard packets until the queue is either empty or the next dialog starts (and dialogs begin with an RTS).
while (true) while (true)
{ {
struct packet_t* packet = queue_peek(&llap_port.out); struct packet_t* packet = queue_peek(&llap_port.out);
if (packet && (packet->type != LLAP_RTS)) if (packet && (packet->type != LLAP_RTS))
{ {
packet = dequeue(&llap_port.out); packet = dequeue(&llap_port.out);
if (packet->data) if (packet->data)
free(packet->data); free(packet->data);
free(packet); free(packet);
} }
else else
break; break;
} }
} }
/** Transfer (send) one LLAP packet from the GS. **/ /** Transfer (send) one LLAP packet from the GS. **/
void llap_enqueue_in(double dcycs, size_t size, byte data[]) void llap_enqueue_in(double dcycs, size_t size, byte data[]) {
{ atbridge_printf("<%0.0f> TX: ", dcycs);
atbridge_printf("<%0.0f> TX: ", dcycs); llap_dump_packet(size, data);
llap_dump_packet(size, data);
if (size < LLAP_PACKET_MIN) if (size < LLAP_PACKET_MIN)
atbridge_printf("ATBridge: Dropping LLAP short packet.\n"); atbridge_printf("ATBridge: Dropping LLAP short packet.\n");
else if (size > LLAP_PACKET_MAX) else if (size > LLAP_PACKET_MAX)
atbridge_printf("ATBridge: Dropping LLAP long packet.\n"); atbridge_printf("ATBridge: Dropping LLAP long packet.\n");
else else
{ {
last_frame_dcycs = dcycs; last_frame_dcycs = dcycs;
LLAP_TYPES type = (LLAP_TYPES)(data[2]); LLAP_TYPES type = (LLAP_TYPES)(data[2]);
switch (type) switch (type)
{ {
case LLAP_DDP_SHORT: case LLAP_DDP_SHORT:
case LLAP_DDP_LONG: case LLAP_DDP_LONG:
llap_handle_data(size, data); llap_handle_data(size, data);
break; break;
case LLAP_ENQ: case LLAP_ENQ:
case LLAP_ACK: case LLAP_ACK:
case LLAP_RTS: case LLAP_RTS:
case LLAP_CTS: case LLAP_CTS:
llap_handle_control(size, data); llap_handle_control(size, data);
break; break;
default: default:
// Intentionally check for valid types and ingore packets with invalid types. // 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. // 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"); atbridge_printf("ATBridge: Dropping LLAP packet with invalid type.\n");
llap_reset_dialog(); llap_reset_dialog();
} }
} }
} }
/** Transfer (receive) one LLAP packet to the GS. **/ /** Transfer (receive) one LLAP packet to the GS. **/
void llap_dequeue_out(double dcycs, size_t* size, byte* data[]) void llap_dequeue_out(double dcycs, size_t* size, byte* data[]) {
{ *size = 0;
*size = 0;
// The LocalTalk protocol requires a minimum 400us gap between dialogs (called the IDG). // The LocalTalk protocol requires a minimum 400us gap between dialogs (called the IDG).
// If necessary, wait for the IDG. // If necessary, wait for the IDG.
if (dialog_state == DIALOG_WAIT_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) // This was the last packet in the dialog.
// The IDG is done. dialog_state = DIALOG_WAIT_IDG;
dialog_state = DIALOG_READY; dialog_end_dcycs = dcycs;
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); 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))) free(packet->data);
{ free(packet);
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);
}
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include <stdbool.h> #include <stdbool.h>
#include "pcap_delay.h" #include "pcap_delay.h"
@ -17,143 +17,130 @@ static void* module = 0;
#endif #endif
bool pcapdelay_load() bool pcapdelay_load() {
{ if (!pcapdelay_is_loaded())
if (!pcapdelay_is_loaded()) {
{
#ifdef WIN32 #ifdef WIN32
module = LoadLibrary("wpcap.dll"); module = LoadLibrary("wpcap.dll");
#elif __linux__ #elif __linux__
module = dlopen("libpcap.so", RTLD_LAZY); module = dlopen("libpcap.so", RTLD_LAZY);
#endif #endif
} }
return pcapdelay_is_loaded(); return pcapdelay_is_loaded();
} }
bool pcapdelay_is_loaded() bool pcapdelay_is_loaded() {
{
#ifdef WIN32 #ifdef WIN32
return module != NULL; return module != NULL;
#elif __linux__ #elif __linux__
return module != 0; return module != 0;
#endif #endif
return 0; return 0;
} }
void pcapdelay_unload() void pcapdelay_unload() {
{ if (pcapdelay_is_loaded())
if (pcapdelay_is_loaded()) {
{
#ifdef WIN32 #ifdef WIN32
FreeLibrary(module); FreeLibrary(module);
module = NULL; module = NULL;
#elif __linux__ #elif __linux__
dlclose(module); dlclose(module);
module = 0; module = 0;
#endif #endif
} }
} }
typedef void (*PFNVOID)(); typedef void (*PFNVOID)();
static PFNVOID delay_load(const char* proc, PFNVOID* ppfn) static PFNVOID delay_load(const char* proc, PFNVOID* ppfn) {
{ if (pcapdelay_load() && proc && ppfn && !*ppfn)
if (pcapdelay_load() && proc && ppfn && !*ppfn) {
{
#ifdef WIN32 #ifdef WIN32
*ppfn = (PFNVOID)GetProcAddress(module, proc); *ppfn = (PFNVOID)GetProcAddress(module, proc);
#elif __linux__ #elif __linux__
*ppfn = (PFNVOID)dlsym(module, proc); *ppfn = (PFNVOID)dlsym(module, proc);
#endif #endif
} }
if (ppfn) if (ppfn)
return *ppfn; return *ppfn;
else else
return 0; return 0;
} }
void pcapdelay_freealldevs(pcap_if_t* a0) void pcapdelay_freealldevs(pcap_if_t* a0) {
{ typedef void (*PFN)(pcap_if_t*);
typedef void (*PFN)(pcap_if_t*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_freealldevs", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_freealldevs", (PFNVOID*)&pfn))) (*pfn)(a0);
(*pfn)(a0);
} }
pcap_t* pcapdelay_open_live(const char* a0, int a1, int a2, int a3, char* a4) 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*);
typedef pcap_t* (*PFN)(const char*, int, int, int, char*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_open_live", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_open_live", (PFNVOID*)&pfn))) return (*pfn)(a0, a1, a2, a3, a4);
return (*pfn)(a0, a1, a2, a3, a4); else
else return 0;
return 0;
} }
void pcapdelay_close(pcap_t* a0) void pcapdelay_close(pcap_t* a0) {
{ typedef void (*PFN)(pcap_t*);
typedef void (*PFN)(pcap_t*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_close", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_close", (PFNVOID*)&pfn))) (*pfn)(a0);
(*pfn)(a0);
} }
int pcapdelay_findalldevs(pcap_if_t** a0, char* a1) int pcapdelay_findalldevs(pcap_if_t** a0, char* a1) {
{ typedef int (*PFN)(pcap_if_t**, char*);
typedef int (*PFN)(pcap_if_t**, char*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_findalldevs", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_findalldevs", (PFNVOID*)&pfn))) return (*pfn)(a0, a1);
return (*pfn)(a0, a1); else
else return 0;
return 0;
} }
int pcapdelay_datalink(pcap_t* a0) int pcapdelay_datalink(pcap_t* a0) {
{ typedef int (*PFN)(pcap_t*);
typedef int(*PFN)(pcap_t*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_datalink", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_datalink", (PFNVOID*)&pfn))) return (*pfn)(a0);
return (*pfn)(a0); else
else return 0;
return 0;
} }
int pcapdelay_setnonblock(pcap_t* a0, int a1, char* a2) int pcapdelay_setnonblock(pcap_t* a0, int a1, char* a2) {
{ typedef int (*PFN)(pcap_t*, int, char*);
typedef int(*PFN)(pcap_t*, int, char*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_setnonblock", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_setnonblock", (PFNVOID*)&pfn))) return (*pfn)(a0, a1, a2);
return (*pfn)(a0, a1, a2); else
else return 0;
return 0;
} }
int pcapdelay_sendpacket(pcap_t* a0, u_char* a1, int a2) int pcapdelay_sendpacket(pcap_t* a0, u_char* a1, int a2) {
{ typedef int (*PFN)(pcap_t*, u_char*, int);
typedef int(*PFN)(pcap_t*, u_char*, int); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_sendpacket", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_sendpacket", (PFNVOID*)&pfn))) return (*pfn)(a0, a1, a2);
return (*pfn)(a0, a1, a2); else
else return 0;
return 0;
} }
const u_char* pcapdelay_next(pcap_t* a0, struct pcap_pkthdr* a1) const u_char* pcapdelay_next(pcap_t* a0, struct pcap_pkthdr* a1) {
{ typedef const u_char*(*PFN)(pcap_t*, struct pcap_pkthdr*);
typedef const u_char*(*PFN)(pcap_t*, struct pcap_pkthdr*); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_next", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_next", (PFNVOID*)&pfn))) return (*pfn)(a0, a1);
return (*pfn)(a0, a1); else
else return 0;
return 0;
} }
int pcapdelay_dispatch(pcap_t* a0, int a1, pcap_handler a2, u_char* a3) 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 *);
typedef const int(*PFN)(pcap_t *, int, pcap_handler, u_char *); static PFN pfn = 0;
static PFN pfn = 0; if ((pfn = (PFN)delay_load("pcap_dispatch", (PFNVOID*)&pfn)))
if ((pfn = (PFN)delay_load("pcap_dispatch", (PFNVOID*)&pfn))) return (*pfn)(a0, a1, a2, a3);
return (*pfn)(a0, a1, a2, a3); else
else return 0;
return 0;
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/** This module implements queues for storing and transferring packets within the bridge. **/ /** This module implements queues for storing and transferring packets within the bridge. **/
@ -11,117 +11,107 @@
#include "atalk.h" #include "atalk.h"
#include "port.h" #include "port.h"
void port_init(struct packet_port_t* port) void port_init(struct packet_port_t* port) {
{ if (port)
if (port) {
{ queue_init(&port->in);
queue_init(&port->in); queue_init(&port->out);
queue_init(&port->out); }
}
} }
void port_shutdown(struct packet_port_t* port) void port_shutdown(struct packet_port_t* port) {
{ if (port)
if (port) {
{ queue_shutdown(&port->in);
queue_shutdown(&port->in); queue_shutdown(&port->out);
queue_shutdown(&port->out); }
}
} }
void queue_init(struct packet_queue_t* queue) void queue_init(struct packet_queue_t* queue) {
{ if (queue)
if (queue) {
{ queue->head = queue->tail = 0;
queue->head = queue->tail = 0; }
}
} }
void queue_shutdown(struct packet_queue_t* queue) void queue_shutdown(struct packet_queue_t* queue) {
{ if (queue)
if (queue) {
{ struct packet_t* packet = dequeue(queue);
struct packet_t* packet = dequeue(queue); while (packet)
while (packet) {
{ if (packet->data)
if (packet->data) free(packet->data);
free(packet->data); free(packet);
free(packet); packet = dequeue(queue);
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[]) 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)
if (!queue) return;
return;
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t)); struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
packet->dest.network = dest.network; packet->dest.network = dest.network;
packet->dest.node = dest.node; packet->dest.node = dest.node;
packet->source.network = source.network; packet->source.network = source.network;
packet->source.node = source.node; packet->source.node = source.node;
packet->type = type; packet->type = type;
packet->size = size; packet->size = size;
packet->data = data; packet->data = data;
enqueue_packet(queue, packet); enqueue_packet(queue, packet);
} }
void enqueue_packet(struct packet_queue_t* queue, struct packet_t* packet) void enqueue_packet(struct packet_queue_t* queue, struct packet_t* packet) {
{ packet->next = 0;
packet->next = 0;
if (queue->tail) if (queue->tail)
queue->tail->next = packet; queue->tail->next = packet;
else else
queue->head = packet; queue->head = packet;
queue->tail = 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[]) 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)
if (!queue) return;
return;
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t)); struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
packet->dest.network = dest.network; packet->dest.network = dest.network;
packet->dest.node = dest.node; packet->dest.node = dest.node;
packet->source.network = source.network; packet->source.network = source.network;
packet->source.node = source.node; packet->source.node = source.node;
packet->type = type; packet->type = type;
packet->size = size; packet->size = size;
packet->data = data; packet->data = data;
insert_packet(queue, packet); insert_packet(queue, packet);
} }
void insert_packet(struct packet_queue_t* queue, struct packet_t* packet) void insert_packet(struct packet_queue_t* queue, struct packet_t* packet) {
{ packet->next = queue->head;
packet->next = queue->head; queue->head = packet;
queue->head = packet; if (!queue->tail)
if (!queue->tail) queue->tail = queue->head;
queue->tail = queue->head;
} }
struct packet_t* dequeue(struct packet_queue_t* queue) struct packet_t* dequeue(struct packet_queue_t* queue) {
{ if (queue && queue->head)
if (queue && queue->head) {
{ struct packet_t* packet = queue->head;
struct packet_t* packet = queue->head; if (queue->tail == queue->head)
if (queue->tail == queue->head) queue->tail = queue->head = 0;
queue->tail = queue->head = 0; else
else queue->head = packet->next;
queue->head = packet->next; return packet;
return packet; }
} else
else return 0;
return 0;
} }
struct packet_t* queue_peek(struct packet_queue_t* queue) struct packet_t* queue_peek(struct packet_queue_t* queue) {
{ if (queue)
if (queue) return queue->head;
return queue->head; else
else return 0;
return 0;
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #include "defc.h"
#include <time.h> #include <time.h>
@ -16,419 +16,396 @@
#endif #endif
extern int Verbose; 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_rom_version;
extern int g_config_gsplus_update_needed; extern int g_config_gsplus_update_needed;
#define CLK_IDLE 1 #define CLK_IDLE 1
#define CLK_TIME 2 #define CLK_TIME 2
#define CLK_INTERNAL 3 #define CLK_INTERNAL 3
#define CLK_BRAM1 4 #define CLK_BRAM1 4
#define CLK_BRAM2 5 #define CLK_BRAM2 5
int g_clk_mode = CLK_IDLE; int g_clk_mode = CLK_IDLE;
int g_clk_read = 0; int g_clk_read = 0;
int g_clk_reg1 = 0; int g_clk_reg1 = 0;
extern int g_c033_data; extern int g_c033_data;
extern int g_c034_val; extern int g_c034_val;
byte g_bram[2][256]; byte g_bram[2][256];
byte *g_bram_ptr = &(g_bram[0][0]); byte *g_bram_ptr = &(g_bram[0][0]);
byte g_temp_boot_slot = 254; byte g_temp_boot_slot = 254;
byte g_orig_boot_slot = 0; byte g_orig_boot_slot = 0;
word32 g_clk_cur_time = 0xa0000000; word32 g_clk_cur_time = 0xa0000000;
int g_clk_next_vbl_update = 0; int g_clk_next_vbl_update = 0;
double double get_dtime() {
get_dtime()
{
#ifndef _WIN32 #ifndef _WIN32
struct timeval tp1; struct timeval tp1;
double dsec; double dsec;
double dusec; double dusec;
#endif #endif
double dtime; double dtime;
/* Routine used to return actual system time as a double */ /* Routine used to return actual system time as a double */
/* No routine cares about the absolute value, only deltas--maybe */ /* No routine cares about the absolute value, only deltas--maybe */
/* take advantage of that in future to increase usec accuracy */ /* take advantage of that in future to increase usec accuracy */
#ifdef _WIN32 #ifdef _WIN32
dtime = timeGetTime() / 1000.0; dtime = timeGetTime() / 1000.0;
#else #else
# ifdef SOLARIS # ifdef SOLARIS
gettimeofday(&tp1, (void *)0); gettimeofday(&tp1, (void *)0);
# else # else
gettimeofday(&tp1, (struct timezone *)0); gettimeofday(&tp1, (struct timezone *)0);
# endif # endif
dsec = (double)tp1.tv_sec; dsec = (double)tp1.tv_sec;
dusec = (double)tp1.tv_usec; dusec = (double)tp1.tv_usec;
dtime = dsec + (dusec / (1000.0 * 1000.0)); dtime = dsec + (dusec / (1000.0 * 1000.0));
#endif #endif
return dtime; return dtime;
} }
int int micro_sleep(double dtime) {
micro_sleep(double dtime)
{
#ifndef _WIN32 #ifndef _WIN32
struct timeval Timer; struct timeval Timer;
int ret; int ret;
#endif #endif
if(dtime <= 0.0) { if(dtime <= 0.0) {
return 0; return 0;
} }
if(dtime >= 1.0) { if(dtime >= 1.0) {
halt_printf("micro_sleep called with %f!!\n", dtime); halt_printf("micro_sleep called with %f!!\n", dtime);
return -1; return -1;
} }
#if 0 #if 0
printf("usleep: %f\n", dtime); printf("usleep: %f\n", dtime);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
Sleep((DWORD)(dtime * 1000)); Sleep((DWORD)(dtime * 1000));
#else #else
Timer.tv_sec = 0; Timer.tv_sec = 0;
Timer.tv_usec = (dtime * 1000000.0); Timer.tv_usec = (dtime * 1000000.0);
if( (ret = select(0, 0, 0, 0, &Timer)) < 0) { if( (ret = select(0, 0, 0, 0, &Timer)) < 0) {
glogf("micro_sleep (select) ret: %d, errno: %d", ret, errno); glogf("micro_sleep (select) ret: %d, errno: %d", ret, errno);
return -1; return -1;
} }
#endif #endif
return 0; return 0;
} }
void void clk_bram_zero() {
clk_bram_zero() int i, j;
{
int i, j;
/* zero out all bram */ /* zero out all bram */
for(i = 0; i < 2; i++) { for(i = 0; i < 2; i++) {
for(j = 0; j < 256; j++) { for(j = 0; j < 256; j++) {
g_bram[i][j] = 0; g_bram[i][j] = 0;
} }
} }
g_bram_ptr = &(g_bram[0][0]); g_bram_ptr = &(g_bram[0][0]);
} }
void void clk_bram_set(int bram_num, int offset, int val) {
clk_bram_set(int bram_num, int offset, int val) g_bram[bram_num][offset] = val;
{
g_bram[bram_num][offset] = val;
} }
extern void x_clk_setup_bram_version(); extern void x_clk_setup_bram_version();
void void clk_setup_bram_version() {
clk_setup_bram_version() x_clk_setup_bram_version();
{
x_clk_setup_bram_version();
} }
void void clk_write_bram(FILE *fconf) {
clk_write_bram(FILE *fconf) int i, j, k;
{
int i, j, k;
for(i = 0; i < 2; i++) { for(i = 0; i < 2; i++) {
fprintf(fconf, "\n"); fprintf(fconf, "\n");
for(j = 0; j < 256; j += 16) { for(j = 0; j < 256; j += 16) {
fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j); fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j);
for(k = 0; k < 16; k++) { for(k = 0; k < 16; k++) {
fprintf(fconf, " %02x", g_bram[i][j+k]); fprintf(fconf, " %02x", g_bram[i][j+k]);
} }
fprintf(fconf, "\n"); fprintf(fconf, "\n");
} }
} }
} }
void void clk_calculate_bram_checksum(void) {
clk_calculate_bram_checksum(void) { int checksum = 0;
int checksum = 0; int i;
int i; if (g_bram_ptr[251] == 0xff) {
if (g_bram_ptr[251] == 0xff) { // Only make the checksum valid if we have non-zeron data!
// Only make the checksum valid if we have non-zeron data! // Otherwise you have very valid zeroes, which confuses the GS firmware mightily.
// Otherwise you have very valid zeroes, which confuses the GS firmware mightily. for (i = 250; i >= 0; i--) {
for (i = 250; i >= 0; i--) { checksum = (checksum & 0xFFFF) << 1;
checksum = (checksum & 0xFFFF) << 1; checksum = (checksum & 0xFFFF)
checksum = (checksum & 0xFFFF) + g_bram_ptr[i]
+ g_bram_ptr[i] + ((int)g_bram_ptr[i + 1] << 8)
+ ((int)g_bram_ptr[i + 1] << 8) + (checksum >> 16);
+ (checksum >> 16); }
} checksum &= 0xFFFF;
checksum &= 0xFFFF; checksum += ((checksum ^ 0xAAAA) << 16);
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 #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[252] = (checksum & 0xFF);
g_bram_ptr[253] = (checksum >> 8); g_bram_ptr[253] = (checksum >> 8);
g_bram_ptr[254] = (checksum >> 16); g_bram_ptr[254] = (checksum >> 16);
g_bram_ptr[255] = (checksum >> 24); g_bram_ptr[255] = (checksum >> 24);
#else #else
g_bram_ptr[255] = (checksum & 0xFF); g_bram_ptr[255] = (checksum & 0xFF);
g_bram_ptr[254] = (checksum >> 8); g_bram_ptr[254] = (checksum >> 8);
g_bram_ptr[253] = (checksum >> 16); g_bram_ptr[253] = (checksum >> 16);
g_bram_ptr[252] = (checksum >> 24); g_bram_ptr[252] = (checksum >> 24);
#endif #endif
} }
} }
void void update_cur_time() {
update_cur_time() struct tm *tm_ptr;
{ time_t cur_time;
struct tm *tm_ptr; unsigned int secs, secs2;
time_t cur_time;
unsigned int secs, secs2;
#ifdef UNDER_CE // OG Not supported on WIndows CE #ifdef UNDER_CE // OG Not supported on WIndows CE
/* /*
SYSTEMTIME stime; SYSTEMTIME stime;
FILETIME ftime; FILETIME ftime;
GetLocalTime(&stime); GetLocalTime(&stime);
SystemTimeToFileTime(&stime,&ftime); SystemTimeToFileTime(&stime,&ftime);
cur_time = ftime.dwLowDateTime; cur_time = ftime.dwLowDateTime;
*/ */
cur_time = time(0); cur_time = time(0);
secs=0; secs=0;
secs2=0; secs2=0;
#else #else
cur_time = time(0); cur_time = time(0);
/* Figure out the timezone (effectively) by diffing two times. */ /* Figure out the timezone (effectively) by diffing two times. */
/* this is probably not right for a few hours around daylight savings*/ /* this is probably not right for a few hours around daylight savings*/
/* time transition */ /* time transition */
secs2 = (unsigned int)mktime(gmtime(&cur_time)); secs2 = (unsigned int)mktime(gmtime(&cur_time));
tm_ptr = localtime(&cur_time); tm_ptr = localtime(&cur_time);
secs = (unsigned int)mktime(tm_ptr); secs = (unsigned int)mktime(tm_ptr);
#ifdef MAC #ifdef MAC
/* Mac OS X's mktime function modifies the tm_ptr passed in for */ /* 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 */ /* the CDT timezone and breaks this algorithm. So on a Mac, we */
/* will use the tm_ptr->gmtoff member to correct the time */ /* will use the tm_ptr->gmtoff member to correct the time */
secs = secs + tm_ptr->tm_gmtoff; secs = secs + tm_ptr->tm_gmtoff;
#else #else
secs = (unsigned int)cur_time - (secs2 - secs); secs = (unsigned int)cur_time - (secs2 - secs);
if(tm_ptr->tm_isdst) { if(tm_ptr->tm_isdst) {
/* adjust for daylight savings time */ /* adjust for daylight savings time */
secs += 3600; secs += 3600;
} }
#endif #endif
#endif #endif
/* add in secs to make date based on Apple Jan 1, 1904 instead of */ /* add in secs to make date based on Apple Jan 1, 1904 instead of */
/* Unix's Jan 1, 1970 */ /* Unix's Jan 1, 1970 */
/* So add in 66 years and 17 leap year days (1904 is a leap year) */ /* So add in 66 years and 17 leap year days (1904 is a leap year) */
secs += ((66*365) + 17) * (24*3600); 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); clk_printf("Update g_clk_cur_time to %08x\n", g_clk_cur_time);
g_clk_next_vbl_update = g_vbl_count + 5; g_clk_next_vbl_update = g_vbl_count + 5;
} }
/* clock_update called by sim65816 every VBL */ /* clock_update called by sim65816 every VBL */
void void clock_update() {
clock_update() /* Nothing to do */
{
/* Nothing to do */
} }
void void clock_update_if_needed() {
clock_update_if_needed() int diff;
{
int diff;
diff = g_clk_next_vbl_update - g_vbl_count; diff = g_clk_next_vbl_update - g_vbl_count;
if(diff < 0 || diff > 60) { if(diff < 0 || diff > 60) {
/* Been a while, re-read the clock */ /* Been a while, re-read the clock */
update_cur_time(); update_cur_time();
} }
} }
void void clock_write_c034(word32 val) {
clock_write_c034(word32 val) g_c034_val = val & 0x7f;
{ if((val & 0x80) != 0) {
g_c034_val = val & 0x7f; if((val & 0x20) == 0) {
if((val & 0x80) != 0) { printf("c034 write not last = 1\n");
if((val & 0x20) == 0) { /* set_halt(1); */
printf("c034 write not last = 1\n"); }
/* set_halt(1); */ do_clock_data();
} }
do_clock_data();
}
} }
void void do_clock_data() {
do_clock_data() word32 mask;
{ int read;
word32 mask; int op;
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; read = g_c034_val & 0x40;
switch(g_clk_mode) { switch(g_clk_mode) {
case CLK_IDLE: case CLK_IDLE:
g_clk_read = (g_c033_data >> 7) & 1; g_clk_read = (g_c033_data >> 7) & 1;
g_clk_reg1 = (g_c033_data >> 2) & 3; g_clk_reg1 = (g_c033_data >> 2) & 3;
op = (g_c033_data >> 4) & 7; op = (g_c033_data >> 4) & 7;
if(!read) { if(!read) {
/* write */ /* write */
switch(op) { switch(op) {
case 0x0: /* Read/write seconds register */ case 0x0: /* Read/write seconds register */
g_clk_mode = CLK_TIME; g_clk_mode = CLK_TIME;
clock_update_if_needed(); clock_update_if_needed();
break; break;
case 0x3: /* internal registers */ case 0x3: /* internal registers */
g_clk_mode = CLK_INTERNAL; g_clk_mode = CLK_INTERNAL;
if(g_clk_reg1 & 0x2) { if(g_clk_reg1 & 0x2) {
/* extend BRAM read */ /* extend BRAM read */
g_clk_mode = CLK_BRAM2; g_clk_mode = CLK_BRAM2;
g_clk_reg1 = (g_c033_data & 7) << 5; g_clk_reg1 = (g_c033_data & 7) << 5;
} }
break; break;
case 0x2: /* read/write ram 0x10-0x13 */ case 0x2: /* read/write ram 0x10-0x13 */
g_clk_mode = CLK_BRAM1; g_clk_mode = CLK_BRAM1;
g_clk_reg1 += 0x10; g_clk_reg1 += 0x10;
break; break;
case 0x4: /* read/write ram 0x00-0x0f */ case 0x4: /* read/write ram 0x00-0x0f */
case 0x5: case 0x6: case 0x7: case 0x5: case 0x6: case 0x7:
g_clk_mode = CLK_BRAM1; g_clk_mode = CLK_BRAM1;
g_clk_reg1 = (g_c033_data >> 2) & 0xf; g_clk_reg1 = (g_c033_data >> 2) & 0xf;
break; break;
default: default:
halt_printf("Bad c033_data in CLK_IDLE: %02x\n", halt_printf("Bad c033_data in CLK_IDLE: %02x\n",
g_c033_data); g_c033_data);
} }
} else { } else {
printf("clk read from IDLE mode!\n"); printf("clk read from IDLE mode!\n");
/* set_halt(1); */ /* set_halt(1); */
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
} }
break; break;
case CLK_BRAM2: case CLK_BRAM2:
if(!read) { if(!read) {
/* get more bits of bram addr */ /* get more bits of bram addr */
if((g_c033_data & 0x83) == 0x00) { if((g_c033_data & 0x83) == 0x00) {
/* more address bits */ /* more address bits */
g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f); g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f);
g_clk_mode = CLK_BRAM1; g_clk_mode = CLK_BRAM1;
} else { } else {
halt_printf("CLK_BRAM2: c033_data: %02x!\n", halt_printf("CLK_BRAM2: c033_data: %02x!\n",
g_c033_data); g_c033_data);
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
} }
} else { } else {
halt_printf("CLK_BRAM2: clock read!\n"); halt_printf("CLK_BRAM2: clock read!\n");
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
} }
break; break;
case CLK_BRAM1: case CLK_BRAM1:
/* access battery ram addr g_clk_reg1 */ /* access battery ram addr g_clk_reg1 */
if(read) { if(read) {
if(g_clk_read) { if(g_clk_read) {
/* Yup, read */ /* Yup, read */
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)){ if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) {
// Modify boot slot // Modify boot slot
g_c033_data = g_temp_boot_slot; g_c033_data = g_temp_boot_slot;
clk_calculate_bram_checksum(); clk_calculate_bram_checksum();
} else { } else {
g_c033_data = g_bram_ptr[g_clk_reg1]; g_c033_data = g_bram_ptr[g_clk_reg1];
} }
clk_printf("Reading BRAM loc %02x: %02x\n", clk_printf("Reading BRAM loc %02x: %02x\n",
g_clk_reg1, g_c033_data); g_clk_reg1, g_c033_data);
} else { } else {
halt_printf("CLK_BRAM1: said wr, now read\n"); halt_printf("CLK_BRAM1: said wr, now read\n");
} }
} else { } else {
if(g_clk_read) { if(g_clk_read) {
halt_printf("CLK_BRAM1: said rd, now write\n"); halt_printf("CLK_BRAM1: said rd, now write\n");
} else { } else {
/* Yup, write */ /* Yup, write */
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) { if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) {
// Modify boot slot // Modify boot slot
g_bram_ptr[g_clk_reg1] = g_temp_boot_slot; g_bram_ptr[g_clk_reg1] = g_temp_boot_slot;
clk_calculate_bram_checksum(); clk_calculate_bram_checksum();
} else { } else {
g_bram_ptr[g_clk_reg1] = g_c033_data; g_bram_ptr[g_clk_reg1] = g_c033_data;
} }
clk_printf("Writing BRAM loc %02x with %02x\n", clk_printf("Writing BRAM loc %02x with %02x\n",
g_clk_reg1, g_c033_data); g_clk_reg1, g_c033_data);
g_config_gsplus_update_needed = 1; g_config_gsplus_update_needed = 1;
} }
} }
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
break; break;
case CLK_TIME: case CLK_TIME:
if(read) { if(read) {
if(g_clk_read == 0) { if(g_clk_read == 0) {
halt_printf("Reading time, but in set mode!\n"); halt_printf("Reading time, but in set mode!\n");
} }
g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) & g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) &
0xff; 0xff;
clk_printf("Returning time byte %d: %02x\n", clk_printf("Returning time byte %d: %02x\n",
g_clk_reg1, g_c033_data); g_clk_reg1, g_c033_data);
} else { } else {
/* Write */ /* Write */
if(g_clk_read) { if(g_clk_read) {
halt_printf("Write time, but in read mode!\n"); halt_printf("Write time, but in read mode!\n");
} }
clk_printf("Writing TIME loc %d with %02x\n", clk_printf("Writing TIME loc %d with %02x\n",
g_clk_reg1, g_c033_data); g_clk_reg1, g_c033_data);
mask = 0xff << (8 * g_clk_reg1); mask = 0xff << (8 * g_clk_reg1);
g_clk_cur_time = (g_clk_cur_time & (~mask)) | g_clk_cur_time = (g_clk_cur_time & (~mask)) |
((g_c033_data & 0xff) << (8 * g_clk_reg1)); ((g_c033_data & 0xff) << (8 * g_clk_reg1));
} }
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
break; break;
case CLK_INTERNAL: case CLK_INTERNAL:
if(read) { if(read) {
printf("Attempting to read internal reg %02x!\n", printf("Attempting to read internal reg %02x!\n",
g_clk_reg1); g_clk_reg1);
} else { } else {
switch(g_clk_reg1) { switch(g_clk_reg1) {
case 0x0: /* test register */ case 0x0: /* test register */
if(g_c033_data & 0xc0) { if(g_c033_data & 0xc0) {
printf("Writing test reg: %02x!\n", printf("Writing test reg: %02x!\n",
g_c033_data); g_c033_data);
/* set_halt(1); */ /* set_halt(1); */
} }
break; break;
case 0x1: /* write protect reg */ case 0x1: /* write protect reg */
clk_printf("Writing clk wr_protect: %02x\n", clk_printf("Writing clk wr_protect: %02x\n",
g_c033_data); g_c033_data);
if(g_c033_data & 0x80) { if(g_c033_data & 0x80) {
printf("Stop, wr clk wr_prot: %02x\n", printf("Stop, wr clk wr_prot: %02x\n",
g_c033_data); g_c033_data);
/* set_halt(1); */ /* set_halt(1); */
} }
break; break;
default: default:
halt_printf("Writing int reg: %02x with %02x\n", halt_printf("Writing int reg: %02x with %02x\n",
g_clk_reg1, g_c033_data); g_clk_reg1, g_c033_data);
} }
} }
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
break; break;
default: default:
halt_printf("clk mode: %d unknown!\n", g_clk_mode); halt_printf("clk mode: %d unknown!\n", g_clk_mode);
g_clk_mode = CLK_IDLE; g_clk_mode = CLK_IDLE;
break; break;
} }
} }

View File

@ -1,8 +1,8 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) 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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -25,7 +32,7 @@ extern const word32 disas_types[256];
extern Engine_reg engine; extern Engine_reg engine;
extern int g_config_control_panel; extern int g_config_control_panel;
extern int g_num_breakpoints; 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 g_dbg_enable_port = 0;
int debug_pause = 0; int debug_pause = 0;
int g_dbg_step = 0; int g_dbg_step = 0;
@ -48,9 +55,9 @@ typedef enum {
G_DBG_COMMAND_ADD_BRK = 8, G_DBG_COMMAND_ADD_BRK = 8,
G_DBG_COMMAND_DEL_BRK = 9, G_DBG_COMMAND_DEL_BRK = 9,
G_DBG_COMMAND_GET_BRK = 0xA, G_DBG_COMMAND_GET_BRK = 0xA,
G_DBG_COMMAND_PAUSE = 0xB, // deprecated G_DBG_COMMAND_PAUSE = 0xB, // deprecated
G_DBG_COMMAND_DEBUGGER = 0xC, // deprecated G_DBG_COMMAND_DEBUGGER = 0xC, // deprecated
G_DBG_COMMAND_QUIT = 0xD, // deprecated G_DBG_COMMAND_QUIT = 0xD, // deprecated
G_DBG_COMMAND_EMU_CMD = 0xE G_DBG_COMMAND_EMU_CMD = 0xE
} G_DBG_COMMANDS; } 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_buffer_4k[4097]; // adding +1 in case someone forgets \0
char tmp_buffer2_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 int timeout; // poll timeout in ms
struct pollfd fds[200]; struct pollfd fds[200];
int nfds = 0, current_size = 0, i, j; 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 */ /* socket debug version */
void void do_go_debug() {
do_go_debug()
{
while (1) { while (1) {
if (g_dbg_step >= 0) { if (g_dbg_step >= 0) {
if (g_dbg_step == 1) { 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; g_config_control_panel = 0;
clear_halt(); clear_halt();
glog("calling run_prog()"); glog("calling run_prog()");
run_prog(); // also calls debug_server_poll() run_prog(); // also calls debug_server_poll()
glog("left run_prog()"); glog("left run_prog()");
step_count++; 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); glogf("debug_push_message() GOT: %d", (int) msg_type);
dbg_cmd_queue[dbg_cmd_queue_len].command = 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 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 dbg_cmd_queue_len++; // INC POINTER
} }
@ -281,8 +286,8 @@ void api_push_memack() {
void api_push_cpu() { void api_push_cpu() {
Engine_reg *eptr; Engine_reg *eptr;
eptr = &engine; eptr = &engine;
int tmp_acc, tmp_x, tmp_y, tmp_psw; int tmp_acc, tmp_x, tmp_y, tmp_psw;
int kpc, direct_page, dbank, stack; int kpc, direct_page, dbank, stack;
kpc = eptr->kpc; kpc = eptr->kpc;
tmp_acc = eptr->acc; tmp_acc = eptr->acc;
@ -293,9 +298,9 @@ void api_push_cpu() {
tmp_y = eptr->yreg; tmp_y = eptr->yreg;
tmp_psw = eptr->psr; tmp_psw = eptr->psr;
int size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),"{\"type\":\"cpu\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"A\":\"%04X\","\ 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\"}}", "\"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); kpc>>16, kpc & 0xffff,tmp_acc,tmp_x,tmp_y,stack,direct_page,dbank, tmp_psw & 0xFFF);
char *msg = (char*)malloc(sizeof(char) * size); char *msg = (char*)malloc(sizeof(char) * size);
strcpy(msg,tmp_buffer_4k); strcpy(msg,tmp_buffer_4k);
@ -303,35 +308,35 @@ void api_push_cpu() {
} }
void api_push_brk() { void api_push_brk() {
int i; int i;
// build our json array of breakpoints // build our json array of breakpoints
tmp_buffer2_4k[0] = '\0'; // start with empty string tmp_buffer2_4k[0] = '\0'; // start with empty string
char *str_ptr = tmp_buffer2_4k; char *str_ptr = tmp_buffer2_4k;
for(i = 0; i < g_num_breakpoints; i++) { for(i = 0; i < g_num_breakpoints; i++) {
//printf("{\"bp:%02x: %06x\n", i, g_breakpts[i]); //printf("{\"bp:%02x: %06x\n", i, g_breakpts[i]);
str_ptr += sprintf(str_ptr, "{\"trig\":\"addr\",\"match\":\"%06X\"}", g_breakpts[i]); str_ptr += sprintf(str_ptr, "{\"trig\":\"addr\",\"match\":\"%06X\"}", g_breakpts[i]);
if (i < g_num_breakpoints-1) { if (i < g_num_breakpoints-1) {
str_ptr += sprintf(str_ptr, ","); 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\":\"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); char *msg = (char*)malloc(sizeof(char) * size);
strcpy(msg,tmp_buffer_4k); strcpy(msg,tmp_buffer_4k);
push_api_msg(size, msg); push_api_msg(size, msg);
} }
void api_push_stack() { void api_push_stack() {
Engine_reg *eptr; Engine_reg *eptr;
eptr = &engine; eptr = &engine;
int kpc, stack; int kpc, stack;
kpc = eptr->kpc; kpc = eptr->kpc;
stack = eptr->stack; 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) // build our json array of 256 stack values ($nn00-nnFF)
char *str_ptr = tmp_buffer2_4k; // (1024B) char *str_ptr = tmp_buffer2_4k; // (1024B)
@ -342,10 +347,10 @@ void api_push_stack() {
str_ptr += sprintf(str_ptr, ","); 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]}}", 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); char *msg = (char*)malloc(sizeof(char) * size);
strcpy(msg,tmp_buffer_4k); strcpy(msg,tmp_buffer_4k);
@ -414,18 +419,18 @@ void api_push_disassembly_chain() {
void api_push_dump(int bank, int start, int end) { void api_push_dump(int bank, int start, int end) {
char *post_str = "\"}}"; char *post_str = "\"}}";
int pre_size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k), int pre_size = snprintf(tmp_buffer_4k, sizeof(tmp_buffer_4k),
"{\"type\":\"mem\",\"data\":{\"bank\":\"%02X\",\"start\":\"%04X\",\"end\":\"%04X\",\"b64data\":\"", "{\"type\":\"mem\",\"data\":{\"bank\":\"%02X\",\"start\":\"%04X\",\"end\":\"%04X\",\"b64data\":\"",
bank, start, end); bank, start, end);
int len = end - start + 1; // +1 for inclusive int len = end - start + 1; // +1 for inclusive
if (len <= 0x10000) { if (len <= 0x10000) {
int b64len = b64encode_len(len); int b64len = b64encode_len(len);
// get pointer to length of full message with data and json wrapper // 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 *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 *str_ptr = msg_json; // msg_json is our big malloced buffer
strcat(str_ptr, tmp_buffer_4k); // prefix string from above strcat(str_ptr, tmp_buffer_4k); // prefix string from above
str_ptr += strlen(tmp_buffer_4k); // move forward the ptr 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 // 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)); char *memchunk = (char*)malloc(sizeof(char) * (len+1));
for (int i = start; i <= end; i++) { 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); b64encode(str_ptr, memchunk, len);
str_ptr = strcat(str_ptr, post_str); // "\"}}" 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(msg_json);
free(memchunk); free(memchunk);
} }
@ -494,7 +499,7 @@ void event_did_step(int step_count) {
api_push_stack(); api_push_stack();
api_push_cpu(); api_push_cpu();
api_push_disassembly(); 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_push_disassembly_start();
} }
api_write_socket(); api_write_socket();
@ -523,7 +528,7 @@ void handle_set_bytes(int address, char *bytes_data) {
while (sscanf(bytes_data, "%02x", &byte) == 1) { while (sscanf(bytes_data, "%02x", &byte) == 1) {
printf("$%02x <---- BYTE @ $%06X\n", byte, address ); printf("$%02x <---- BYTE @ $%06X\n", byte, address );
bytes_data += 2; bytes_data += 2;
address ++; address++;
set_byte_at_address(address, byte & 0xFF); set_byte_at_address(address, byte & 0xFF);
} }
} }
@ -536,15 +541,15 @@ void event_set_mem(char *str) {
char *pch; char *pch;
pch = strtok (str," "); // split our memory sets on spaces pch = strtok (str," "); // split our memory sets on spaces
while (pch != NULL) { while (pch != NULL) {
sscanf(pch, "%06X", &address); sscanf(pch, "%06X", &address);
bytes_data = pch+6; bytes_data = pch+6;
printf("BytesData %s\n", bytes_data); printf("BytesData %s\n", bytes_data);
// for each token go try to handle it // for each token go try to handle it
handle_set_bytes(address, bytes_data); handle_set_bytes(address, bytes_data);
pch = strtok (NULL, " "); pch = strtok (NULL, " ");
} }
api_push_memack(); // send ack api_push_memack(); // send ack
api_write_socket(); api_write_socket();
@ -586,13 +591,13 @@ void event_emu_cmd(char *str) {
pch = strtok (str," "); pch = strtok (str," ");
while (pch != NULL) while (pch != NULL)
{ {
cmd_char = pch[0]; cmd_char = pch[0];
cmd_data = pch+1; cmd_data = pch+1;
if (cmd_data[0] == '\0') { if (cmd_data[0] == '\0') {
cmd_data = NULL; cmd_data = NULL;
} }
// for each token go try to handle it // for each token go try to handle it
handle_emu_cmd(cmd_char, cmd_data); handle_emu_cmd(cmd_char, cmd_data);
pch = strtok (NULL, " "); pch = strtok (NULL, " ");
} }
@ -694,13 +699,13 @@ void event_set_cpu(char *str) {
char * pch; char * pch;
pch = strtok (str," "); pch = strtok (str," ");
while (pch != NULL) { while (pch != NULL) {
cmd_char = pch[0]; cmd_char = pch[0];
cmd_data = pch+1; cmd_data = pch+1;
if (cmd_data[0] == '\0') { if (cmd_data[0] == '\0') {
cmd_data = NULL; cmd_data = NULL;
} }
// for each token go try to handle it // for each token go try to handle it
handle_cpu_cmd(cmd_char, cmd_data); handle_cpu_cmd(cmd_char, cmd_data);
pch = strtok (NULL, " "); pch = strtok (NULL, " ");
} }
@ -791,7 +796,7 @@ void debug_setup_socket() {
/*************************************************************/ /*************************************************************/
/* Initialize the pollfd structure */ /* Initialize the pollfd structure */
/*************************************************************/ /*************************************************************/
memset(fds, 0 , sizeof(fds)); memset(fds, 0, sizeof(fds));
/*************************************************************/ /*************************************************************/
/* Set up the initial listening socket */ /* Set up the initial listening socket */
@ -836,7 +841,7 @@ void api_write_socket() {
// message_string is now built! we can send it. // message_string is now built! we can send it.
dbg_msg_queue_len = 0; // clear msg queue 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 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) { int writeDataToClient(int sckt, const void *data, int datalen) {
const char *pdata = (const char*) data; const char *pdata = (const char*) data;
while (datalen > 0){ while (datalen > 0) {
int numSent = send(sckt, pdata, 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"); printf("The client was not written to: disconnected\n");
} else { } else {
perror("The client was not written to"); perror("The client was not written to");
@ -1051,10 +1056,10 @@ void debug_server_poll() {
char *mesg_ptr = buffer; char *mesg_ptr = buffer;
char *split_ptr = strchr(mesg_ptr, '\n'); 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) { if(split_ptr) {
int index = split_ptr - buffer; 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; int debug_echo = FALSE;
while (mesg_ptr < buffer + len - 1) { 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); debug_push_message(G_DBG_COMMAND_GET_BRK, mesg_ptr+1, mesg_len);
break; break;
case 'b': // DEPRECATED case 'b': // DEPRECATED
debug_push_message(G_DBG_COMMAND_PAUSE, mesg_ptr+1, mesg_len); debug_push_message(G_DBG_COMMAND_PAUSE, mesg_ptr+1, mesg_len);
break; break;
case 'c': // DEPRECATED case 'c': // DEPRECATED
debug_push_message(G_DBG_COMMAND_DEBUGGER, mesg_ptr+1, mesg_len); debug_push_message(G_DBG_COMMAND_DEBUGGER, mesg_ptr+1, mesg_len);
break; break;
case 'd': // DEPRECATED ???? case 'd': // DEPRECATED ????
debug_push_message(G_DBG_COMMAND_QUIT, mesg_ptr+1, mesg_len); debug_push_message(G_DBG_COMMAND_QUIT, mesg_ptr+1, mesg_len);
break; break;
@ -1119,11 +1124,11 @@ void debug_server_poll() {
// @TODO probably send error response // @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'); split_ptr = strchr(mesg_ptr, '\n');
if(split_ptr) { if(split_ptr) {
int index = split_ptr - mesg_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++) { for (i = 0; i < nfds; i++) {
if(fds[i].fd >= 0) if(fds[i].fd >= 0)
close(fds[i].fd); close(fds[i].fd);
} }
nfds = 0; nfds = 0;
} }
@ -1196,12 +1201,12 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
const char *out; const char *out;
int args, type; int args, type;
int opcode; int opcode;
word32 val; word32 val;
word32 oldkpc; word32 oldkpc;
word32 dtype; word32 dtype;
int signed_val; int signed_val;
oldkpc = kpc; oldkpc = kpc;
if(op_provided) { if(op_provided) {
@ -1228,33 +1233,33 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
val = -1; val = -1;
switch(args) { switch(args) {
case 0: case 0:
val = 0; val = 0;
break; break;
case 1: case 1:
if(op_provided) { if(op_provided) {
val = instr & 0xff; val = instr & 0xff;
} else { } else {
val = get_memory_c(kpc, 0); val = get_memory_c(kpc, 0);
} }
break; break;
case 2: case 2:
if(op_provided) { if(op_provided) {
val = instr & 0xffff; val = instr & 0xffff;
} else { } else {
val = get_memory16_c(kpc, 0); val = get_memory16_c(kpc, 0);
} }
break; break;
case 3: case 3:
if(op_provided) { if(op_provided) {
val = instr & 0xffffff; val = instr & 0xffffff;
} else { } else {
val = get_memory24_c(kpc, 0); val = get_memory24_c(kpc, 0);
} }
break; break;
default: default:
fprintf(stderr, "args out of range: %d, opcode: %08x\n", fprintf(stderr, "args out of range: %d, opcode: %08x\n",
args, opcode); args, opcode);
break; break;
} }
kpc += args; kpc += args;
@ -1264,171 +1269,171 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
switch(type) { switch(type) {
case ABS: case ABS:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%04x",out,val); sprintf(buf_disasm,"%s $%04x",out,val);
break; break;
case ABSX: case ABSX:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%04x,X",out,val); sprintf(buf_disasm,"%s $%04x,X",out,val);
break; break;
case ABSY: case ABSY:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%04x,Y",out,val); sprintf(buf_disasm,"%s $%04x,Y",out,val);
break; break;
case ABSLONG: case ABSLONG:
if(args != 3) { if(args != 3) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%06x",out,val); sprintf(buf_disasm,"%s $%06x",out,val);
break; break;
case ABSIND: case ABSIND:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s ($%04x)",out,val); sprintf(buf_disasm,"%s ($%04x)",out,val);
break; break;
case ABSXIND: case ABSXIND:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s ($%04x,X)",out,val); sprintf(buf_disasm,"%s ($%04x,X)",out,val);
break; break;
case IMPLY: case IMPLY:
if(args != 0) { if(args != 0) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s",out); sprintf(buf_disasm,"%s",out);
break; break;
case ACCUM: case ACCUM:
if(args != 0) { if(args != 0) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s",out); sprintf(buf_disasm,"%s",out);
break; break;
case IMMED: case IMMED:
if(args == 1) { if(args == 1) {
sprintf(buf_disasm,"%s #$%02x",out,val); sprintf(buf_disasm,"%s #$%02x",out,val);
} else if(args == 2) { } else if(args == 2) {
sprintf(buf_disasm,"%s #$%04x",out,val); sprintf(buf_disasm,"%s #$%04x",out,val);
} else { } else {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
break; break;
case JUST8: case JUST8:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%02x",out,val); sprintf(buf_disasm,"%s $%02x",out,val);
break; break;
case DLOC: case DLOC:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%02x",out,val); sprintf(buf_disasm,"%s $%02x",out,val);
break; break;
case DLOCX: case DLOCX:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%02x,X",out,val); sprintf(buf_disasm,"%s $%02x,X",out,val);
break; break;
case DLOCY: case DLOCY:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%02x,Y",out,val); sprintf(buf_disasm,"%s $%02x,Y",out,val);
break; break;
case LONG: case LONG:
if(args != 3) { if(args != 3) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%06x",out,val); sprintf(buf_disasm,"%s $%06x",out,val);
break; break;
case LONGX: case LONGX:
if(args != 3) { if(args != 3) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%06x,X",out,val); sprintf(buf_disasm,"%s $%06x,X",out,val);
break; break;
case DLOCIND: case DLOCIND:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s ($%02x)",out,val); sprintf(buf_disasm,"%s ($%02x)",out,val);
break; break;
case DLOCINDY: case DLOCINDY:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s ($%02x),Y",out,val); sprintf(buf_disasm,"%s ($%02x),Y",out,val);
break; break;
case DLOCXIND: case DLOCXIND:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s ($%02x,X)",out,val); sprintf(buf_disasm,"%s ($%02x,X)",out,val);
break; break;
case DLOCBRAK: case DLOCBRAK:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s [$%02x]",out,val); sprintf(buf_disasm,"%s [$%02x]",out,val);
break; break;
case DLOCBRAKY: case DLOCBRAKY:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s [$%02x],y",out,val); sprintf(buf_disasm,"%s [$%02x],y",out,val);
break; break;
case DISP8: case DISP8:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
signed_val = (signed char)val; signed_val = (signed char)val;
sprintf(buf_disasm,"%s $%04x",out, sprintf(buf_disasm,"%s $%04x",out,
(word32)(kpc+(signed_val)) & 0xffff); (word32)(kpc+(signed_val)) & 0xffff);
break; break;
case DISP8S: case DISP8S:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%02x,S",out,(word32)(byte)(val)); sprintf(buf_disasm,"%s $%02x,S",out,(word32)(byte)(val));
break; break;
case DISP8SINDY: case DISP8SINDY:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s ($%02x,S),Y",out,(word32)(byte)(val)); sprintf(buf_disasm,"%s ($%02x,S),Y",out,(word32)(byte)(val));
break; break;
case DISP16: case DISP16:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%04x", out, sprintf(buf_disasm,"%s $%04x", out,
(word32)(kpc+(signed)(word16)(val)) & 0xffff); (word32)(kpc+(signed)(word16)(val)) & 0xffff);
break; break;
case MVPMVN: case MVPMVN:
if(args != 2) { if(args != 2) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s $%02x,$%02x",out,val&0xff,val>>8); sprintf(buf_disasm,"%s $%02x,$%02x",out,val&0xff,val>>8);
break; break;
case SEPVAL: case SEPVAL:
case REPVAL: case REPVAL:
if(args != 1) { if(args != 1) {
printf("arg # mismatch for opcode %x\n", opcode); printf("arg # mismatch for opcode %x\n", opcode);
} }
sprintf(buf_disasm,"%s #$%02x",out,val); sprintf(buf_disasm,"%s #$%02x",out,val);
break; break;
default: default:
printf("argument type: %d unexpected\n", type); printf("argument type: %d unexpected\n", type);
break; break;
} }
@ -1437,26 +1442,26 @@ int do_dis_json(char *buf, word32 kpc, int accsize, int xsize, int op_provided,
opcode = (operand >> 24) & 0xff; opcode = (operand >> 24) & 0xff;
switch (args+1) { switch (args+1) {
case 1: case 1:
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\"]", opcode); snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\"]", opcode);
break; break;
case 2: case 2:
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\"]", opcode, instr & 0xff); snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\"]", opcode, instr & 0xff);
break; break;
case 3: case 3:
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8); snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8);
break; break;
case 4: case 4:
snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8, (instr & 0xff0000) >> 16); snprintf(buf_instructions, sizeof(buf_instructions),"[\"%02X\",\"%02X\",\"%02X\",\"%02X\"]", opcode, instr & 0xff, (instr & 0xff00) >> 8, (instr & 0xff0000) >> 16);
break; break;
default: default:
break; break;
} }
// @TODO: FIX!!! NEEDS REAL BUFFER SIZE, note magic 1024 // @TODO: FIX!!! NEEDS REAL BUFFER SIZE, note magic 1024
snprintf(buf, 1024,"{\"type\":\"dis\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"bytes\":%s,"\ snprintf(buf, 1024,"{\"type\":\"dis\",\"data\":{\"K\":\"%02X\",\"PC\":\"%04X\",\"bytes\":%s," \
"\"disasm\":\"%s\",\"chain\":\"%d\"}}", "\"disasm\":\"%s\",\"chain\":\"%d\"}}",
oldkpc>>16, oldkpc & 0xffff ,buf_instructions, buf_disasm, chain); oldkpc>>16, oldkpc & 0xffff,buf_instructions, buf_disasm, chain);
return(args+1); return(args+1);
} }
@ -1488,7 +1493,7 @@ int b64encode(char *encoded, const char *string, int len) {
*p++ = '='; *p++ = '=';
} else { } else {
*p++ = b64chars[((string[i] & 0x3) << 4) | *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++ = b64chars[((string[i + 1] & 0xF) << 2)];
} }
*p++ = '='; *p++ = '=';

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defcomm.h" #include "defcomm.h"
@ -12,8 +12,8 @@
#include <stdio.h> #include <stdio.h>
extern "C" int outputInfo(const char* format,...); extern "C" int outputInfo(const char* format,...);
extern "C" int fOutputInfo(FILE*,const char* format,...); extern "C" int fOutputInfo(FILE*,const char* format,...);
#define printf outputInfo #define printf outputInfo
#define fprintf fOutputInfo #define fprintf fOutputInfo
#endif #endif
#define STRUCT(a) typedef struct _ ## a a; struct _ ## a #define STRUCT(a) typedef struct _ ## a a; struct _ ## a
@ -30,31 +30,31 @@ typedef unsigned long long word64;
void U_STACK_TRACE(); void U_STACK_TRACE();
/* 28MHz crystal, plus every 65th 1MHz cycle is stretched 140ns */ /* 28MHz crystal, plus every 65th 1MHz cycle is stretched 140ns */
#define CYCS_28_MHZ (28636360) #define CYCS_28_MHZ (28636360)
#define DCYCS_28_MHZ (1.0*CYCS_28_MHZ) #define DCYCS_28_MHZ (1.0*CYCS_28_MHZ)
#define CYCS_3_5_MHZ (CYCS_28_MHZ/8) #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 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_1_MHZ ((int)DCYCS_1_MHZ)
/* #define DCYCS_IN_16MS_RAW (DCYCS_1_MHZ / 60.0) */ /* #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 */ /* Use precisely 17030 instead of forcing 60 Hz since this is the number of */
/* 1MHz cycles per screen */ /* 1MHz cycles per screen */
#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW)) #define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW))
#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS)) #define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS))
#ifdef GSPLUS_LITTLE_ENDIAN #ifdef GSPLUS_LITTLE_ENDIAN
// @todo: look at using <byteswap.h> for fastest platform implementations // @todo: look at using <byteswap.h> for fastest platform implementations
# define BIGEND(a) ((((a) >> 24) & 0xff) + \ # define BIGEND(a) ((((a) >> 24) & 0xff) + \
(((a) >> 8) & 0xff00) + \ (((a) >> 8) & 0xff00) + \
(((a) << 8) & 0xff0000) + \ (((a) << 8) & 0xff0000) + \
(((a) << 24) & 0xff000000)) (((a) << 24) & 0xff000000))
# define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00)) # define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00))
# define GET_BE_WORD32(a) (BIGEND(a)) # define GET_BE_WORD32(a) (BIGEND(a))
#else #else
# define BIGEND(a) (a) # define BIGEND(a) (a)
# define GET_BE_WORD16(a) (a) # define GET_BE_WORD16(a) (a)
# define GET_BE_WORD32(a) (a) # define GET_BE_WORD32(a) (a)
#endif #endif
#define MAXNUM_HEX_PER_LINE 32 #define MAXNUM_HEX_PER_LINE 32
@ -63,7 +63,7 @@ void U_STACK_TRACE();
# include <libc.h> # include <libc.h>
#endif #endif
#if !defined(_WIN32) && !defined(UNDER_CE) // OG #if !defined(_WIN32) && !defined(UNDER_CE) // OG
# include <unistd.h> # include <unistd.h>
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <sys/wait.h> # include <sys/wait.h>
@ -77,7 +77,7 @@ void U_STACK_TRACE();
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#ifndef UNDER_CE // OG CE SPecific #ifndef UNDER_CE // OG CE SPecific
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -93,24 +93,24 @@ extern int open(const char* name,int,...);
extern int read(int,char*,int); extern int read(int,char*,int);
extern int close(int); extern int close(int);
extern int write( int fd, const void *buffer, unsigned int count ); 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; }; struct stat { int st_size; };
extern int stat(const char* name, struct stat*); extern int stat(const char* name, struct stat*);
extern int fstat(int, struct stat*); extern int fstat(int, struct stat*);
#define O_RDWR 1 #define O_RDWR 1
#define O_BINARY 2 #define O_BINARY 2
#define O_RDONLY 4 #define O_RDONLY 4
#define O_WRONLY 8 #define O_WRONLY 8
#define O_CREAT 16 #define O_CREAT 16
#define O_TRUNC 32 #define O_TRUNC 32
#define EAGAIN 11 #define EAGAIN 11
#define EINTR 4 #define EINTR 4
#endif #endif
#ifdef HPUX #ifdef HPUX
# include <machine/inline.h> /* for GET_ITIMER */ # include <machine/inline.h> /* for GET_ITIMER */
#endif #endif
#ifdef SOLARIS #ifdef SOLARIS
@ -119,232 +119,232 @@ extern int fstat(int, struct stat*);
#ifndef O_BINARY #ifndef O_BINARY
/* work around some Windows junk */ /* work around some Windows junk */
# define O_BINARY 0 # define O_BINARY 0
#endif #endif
STRUCT(Pc_log) { STRUCT(Pc_log) {
double dcycs; double dcycs;
word32 dbank_kpc; word32 dbank_kpc;
word32 instr; word32 instr;
word32 psr_acc; word32 psr_acc;
word32 xreg_yreg; word32 xreg_yreg;
word32 stack_direct; word32 stack_direct;
word32 pad; word32 pad;
}; };
STRUCT(Data_log) { STRUCT(Data_log) {
double dcycs; double dcycs;
word32 addr; word32 addr;
word32 val; word32 val;
word32 size; word32 size;
}; };
STRUCT(Event) { STRUCT(Event) {
double dcycs; double dcycs;
int type; int type;
Event *next; Event *next;
}; };
STRUCT(Fplus) { STRUCT(Fplus) {
double plus_1; double plus_1;
double plus_2; double plus_2;
double plus_3; double plus_3;
double plus_x_minus_1; double plus_x_minus_1;
}; };
STRUCT(Engine_reg) { STRUCT(Engine_reg) {
double fcycles; double fcycles;
word32 kpc; word32 kpc;
word32 acc; word32 acc;
word32 xreg; word32 xreg;
word32 yreg; word32 yreg;
word32 stack; word32 stack;
word32 dbank; word32 dbank;
word32 direct; word32 direct;
word32 psr; word32 psr;
Fplus *fplus_ptr; Fplus *fplus_ptr;
}; };
STRUCT(Kimage) { STRUCT(Kimage) {
void *dev_handle; void *dev_handle;
void *dev_handle2; void *dev_handle2;
byte *data_ptr; byte *data_ptr;
int width_req; int width_req;
int width_act; int width_act;
int height; int height;
int depth; int depth;
int mdepth; int mdepth;
int aux_info; int aux_info;
}; };
typedef byte *Pg_info; typedef byte *Pg_info;
STRUCT(Page_info) { STRUCT(Page_info) {
Pg_info rd_wr; Pg_info rd_wr;
}; };
STRUCT(Cfg_menu) { STRUCT(Cfg_menu) {
const char *str; const char *str;
void *ptr; void *ptr;
const char *name_str; const char *name_str;
void *defptr; void *defptr;
int cfgtype; int cfgtype;
}; };
STRUCT(Cfg_dirent) { STRUCT(Cfg_dirent) {
char *name; char *name;
int is_dir; int is_dir;
int size; int size;
int image_start; int image_start;
int part_num; int part_num;
}; };
STRUCT(Cfg_listhdr) { STRUCT(Cfg_listhdr) {
Cfg_dirent *direntptr; Cfg_dirent *direntptr;
int max; int max;
int last; int last;
int invalid; int invalid;
int curent; int curent;
int topent; int topent;
int num_to_show; int num_to_show;
}; };
STRUCT(Emustate_intlist) { STRUCT(Emustate_intlist) {
const char *str; const char *str;
int *iptr; int *iptr;
}; };
STRUCT(Emustate_dbllist) { STRUCT(Emustate_dbllist) {
const char *str; const char *str;
double *dptr; double *dptr;
}; };
STRUCT(Emustate_word32list) { STRUCT(Emustate_word32list) {
const char *str; const char *str;
word32 *wptr; word32 *wptr;
}; };
#ifdef __LP64__ #ifdef __LP64__
# define PTR2WORD(a) ((unsigned long)(a)) # define PTR2WORD(a) ((unsigned long)(a))
#else #else
# define PTR2WORD(a) ((unsigned int)(a)) # define PTR2WORD(a) ((unsigned int)(a))
#endif #endif
#define ALTZP (g_c068_statereg & 0x80) #define ALTZP (g_c068_statereg & 0x80)
/* #define PAGE2 (g_c068_statereg & 0x40) */ /* #define PAGE2 (g_c068_statereg & 0x40) */
#define RAMRD (g_c068_statereg & 0x20) #define RAMRD (g_c068_statereg & 0x20)
#define RAMWRT (g_c068_statereg & 0x10) #define RAMWRT (g_c068_statereg & 0x10)
#define RDROM (g_c068_statereg & 0x08) #define RDROM (g_c068_statereg & 0x08)
#define LCBANK2 (g_c068_statereg & 0x04) #define LCBANK2 (g_c068_statereg & 0x04)
#define ROMB (g_c068_statereg & 0x02) #define ROMB (g_c068_statereg & 0x02)
#define INTCX (g_c068_statereg & 0x01) #define INTCX (g_c068_statereg & 0x01)
#define C041_EN_25SEC_INTS 0x10 #define C041_EN_25SEC_INTS 0x10
#define C041_EN_VBL_INTS 0x08 #define C041_EN_VBL_INTS 0x08
#define C041_EN_SWITCH_INTS 0x04 #define C041_EN_SWITCH_INTS 0x04
#define C041_EN_MOVE_INTS 0x02 #define C041_EN_MOVE_INTS 0x02
#define C041_EN_MOUSE 0x01 #define C041_EN_MOUSE 0x01
/* WARNING: SCC1 and SCC0 interrupts must be in this order for scc.c */ /* WARNING: SCC1 and SCC0 interrupts must be in this order for scc.c */
/* This order matches the SCC hardware */ /* This order matches the SCC hardware */
#define IRQ_PENDING_SCC1_ZEROCNT 0x00001 #define IRQ_PENDING_SCC1_ZEROCNT 0x00001
#define IRQ_PENDING_SCC1_TX 0x00002 #define IRQ_PENDING_SCC1_TX 0x00002
#define IRQ_PENDING_SCC1_RX 0x00004 #define IRQ_PENDING_SCC1_RX 0x00004
#define IRQ_PENDING_SCC0_ZEROCNT 0x00008 #define IRQ_PENDING_SCC0_ZEROCNT 0x00008
#define IRQ_PENDING_SCC0_TX 0x00010 #define IRQ_PENDING_SCC0_TX 0x00010
#define IRQ_PENDING_SCC0_RX 0x00020 #define IRQ_PENDING_SCC0_RX 0x00020
#define IRQ_PENDING_C023_SCAN 0x00100 #define IRQ_PENDING_C023_SCAN 0x00100
#define IRQ_PENDING_C023_1SEC 0x00200 #define IRQ_PENDING_C023_1SEC 0x00200
#define IRQ_PENDING_C046_25SEC 0x00400 #define IRQ_PENDING_C046_25SEC 0x00400
#define IRQ_PENDING_C046_VBL 0x00800 #define IRQ_PENDING_C046_VBL 0x00800
#define IRQ_PENDING_ADB_KBD_SRQ 0x01000 #define IRQ_PENDING_ADB_KBD_SRQ 0x01000
#define IRQ_PENDING_ADB_DATA 0x02000 #define IRQ_PENDING_ADB_DATA 0x02000
#define IRQ_PENDING_ADB_MOUSE 0x04000 #define IRQ_PENDING_ADB_MOUSE 0x04000
#define IRQ_PENDING_DOC 0x08000 #define IRQ_PENDING_DOC 0x08000
#define EXTRU(val, pos, len) \ #define EXTRU(val, pos, len) \
( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \ ( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \
(((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) ) (((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) )
#define DEP1(val, pos, old_val) \ #define DEP1(val, pos, old_val) \
(((old_val) & ~(1 << (31 - (pos))) ) | \ (((old_val) & ~(1 << (31 - (pos))) ) | \
( ((val) & 1) << (31 - (pos))) ) ( ((val) & 1) << (31 - (pos))) )
#define set_halt(val) \ #define set_halt(val) \
if(val) { set_halt_act(val); } if(val) { set_halt_act(val); }
#define clear_halt() \ #define clear_halt() \
clr_halt_act() clr_halt_act()
#define GET_PAGE_INFO_RD(page) \ #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) \ #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) \ #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) \ #define SET_PAGE_INFO_WR(page,val) \
;page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = \ ; page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = \
(Pg_info)val; (Pg_info)val;
#define VERBOSE_DISK 0x001 #define VERBOSE_DISK 0x001
#define VERBOSE_IRQ 0x002 #define VERBOSE_IRQ 0x002
#define VERBOSE_CLK 0x004 #define VERBOSE_CLK 0x004
#define VERBOSE_SHADOW 0x008 #define VERBOSE_SHADOW 0x008
#define VERBOSE_IWM 0x010 #define VERBOSE_IWM 0x010
#define VERBOSE_DOC 0x020 #define VERBOSE_DOC 0x020
#define VERBOSE_ADB 0x040 #define VERBOSE_ADB 0x040
#define VERBOSE_SCC 0x080 #define VERBOSE_SCC 0x080
#define VERBOSE_TEST 0x100 #define VERBOSE_TEST 0x100
#define VERBOSE_VIDEO 0x200 #define VERBOSE_VIDEO 0x200
#define VERBOSE_MAC 0x400 #define VERBOSE_MAC 0x400
#ifdef NO_VERB #ifdef NO_VERB
# define DO_VERBOSE 0 # define DO_VERBOSE 0
#else #else
# define DO_VERBOSE 1 # define DO_VERBOSE 1
#endif #endif
#define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf #define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf
#define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf #define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf
#define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf #define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf
#define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf #define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf
#define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf #define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf
#define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf #define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf
#define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf #define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf
#define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf #define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf
#define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf #define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf
#define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf #define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf
#define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf #define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf
#define HALT_ON_SCAN_INT 0x001 #define HALT_ON_SCAN_INT 0x001
#define HALT_ON_IRQ 0x002 #define HALT_ON_IRQ 0x002
#define HALT_ON_SHADOW_REG 0x004 #define HALT_ON_SHADOW_REG 0x004
#define HALT_ON_C70D_WRITES 0x008 #define HALT_ON_C70D_WRITES 0x008
#define HALT_ON(a, msg) \ #define HALT_ON(a, msg) \
if(Halt_on & a) { \ if(Halt_on & a) { \
halt_printf(msg); \ halt_printf(msg); \
} }
#ifndef MIN #ifndef MIN
# define MIN(a,b) (((a) < (b)) ? (a) : (b)) # define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif #endif
#ifndef MAX #ifndef MAX
# define MAX(a,b) (((a) < (b)) ? (b) : (a)) # define MAX(a,b) (((a) < (b)) ? (b) : (a))
#endif #endif
#define GET_ITIMER(dest) dest = get_itimer(); #define GET_ITIMER(dest) dest = get_itimer();
#include "iwm.h" #include "iwm.h"
#include "protos.h" #include "protos.h"
@ -353,7 +353,7 @@ STRUCT(Emustate_word32list) {
#define JOYSTICK_TYPE_MOUSE 1 #define JOYSTICK_TYPE_MOUSE 1
#define JOYSTICK_TYPE_NATIVE_1 2 #define JOYSTICK_TYPE_NATIVE_1 2
#define JOYSTICK_TYPE_NATIVE_2 3 #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 #define NB_JOYSTICK_TYPE 5
// starting window x/y position if Undefined // 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/* /*
* fbdriver - Linux fullscreen framebuffer graphics driver * 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_a2palette_8to1624[256];
extern word32 g_a2_screen_buffer_changed; extern word32 g_a2_screen_buffer_changed;
extern word32 g_c025_val; extern word32 g_c025_val;
#define SHIFT_DOWN ( (g_c025_val & 0x01) ) #define SHIFT_DOWN ( (g_c025_val & 0x01) )
#define CTRL_DOWN ( (g_c025_val & 0x02) ) #define CTRL_DOWN ( (g_c025_val & 0x02) )
#define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) ) #define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) )
#define OPTION_DOWN ( (g_c025_val & 0x40) ) #define OPTION_DOWN ( (g_c025_val & 0x40) )
#define CMD_DOWN ( (g_c025_val & 0x80) ) #define CMD_DOWN ( (g_c025_val & 0x80) )
extern int g_video_act_margin_left; extern int g_video_act_margin_left;
extern int g_video_act_margin_right; extern int g_video_act_margin_right;
extern int g_video_act_margin_top; extern int g_video_act_margin_top;
@ -53,491 +53,469 @@ extern int g_green_right_shift;
extern int g_blue_right_shift; extern int g_blue_right_shift;
extern Kimage g_mainwin_kimage; extern Kimage g_mainwin_kimage;
int keycode_to_a2code[128] = int keycode_to_a2code[128] =
{ {
-1, // KEY_RESERVED -1, // KEY_RESERVED
0x35, // KEY_ESC 0x35, // KEY_ESC
0x12, // KEY_1 0x12, // KEY_1
0x13, // KEY_2 0x13, // KEY_2
0x14, // KEY_3 0x14, // KEY_3
0x15, // KEY_4 0x15, // KEY_4
0x17, // KEY_5 0x17, // KEY_5
0x16, // KEY_6 0x16, // KEY_6
0x1A, // KEY_7 0x1A, // KEY_7
0x1C, // KEY_8 0x1C, // KEY_8
0x19, // KEY_9 0x19, // KEY_9
0x1D, // KEY_0 0x1D, // KEY_0
0x1B, // KEY_MINUS 0x1B, // KEY_MINUS
0x18, // KEY_EQUAL 0x18, // KEY_EQUAL
0x3B, // KEY_BACKSPACE0 0x3B, // KEY_BACKSPACE0
0x30, // KEY_TAB 0x30, // KEY_TAB
0x0C, // KEY_Q 0x0C, // KEY_Q
0x0D, // KEY_W 0x0D, // KEY_W
0x0E, // KEY_E 0x0E, // KEY_E
0x0F, // KEY_R 0x0F, // KEY_R
0x11, // KEY_T 0x11, // KEY_T
0x10, // KEY_Y 0x10, // KEY_Y
0x20, // KEY_U 0x20, // KEY_U
0x22, // KEY_I 0x22, // KEY_I
0x1F, // KEY_O 0x1F, // KEY_O
0x23, // KEY_P 0x23, // KEY_P
0x21, // KEY_LEFTBRACE 0x21, // KEY_LEFTBRACE
0x1E, // KEY_RIGHTBRACE 0x1E, // KEY_RIGHTBRACE
0x24, // KEY_ENTER 0x24, // KEY_ENTER
0x36, // KEY_LEFTCTRL 0x36, // KEY_LEFTCTRL
0x00, // KEY_A 0x00, // KEY_A
0x01, // KEY_S 0x01, // KEY_S
0x02, // KEY_D 0x02, // KEY_D
0x03, // KEY_F 0x03, // KEY_F
0x05, // KEY_G 0x05, // KEY_G
0x04, // KEY_H 0x04, // KEY_H
0x26, // KEY_J 0x26, // KEY_J
0x28, // KEY_K 0x28, // KEY_K
0x25, // KEY_L 0x25, // KEY_L
0x29, // KEY_SEMICOLON 0x29, // KEY_SEMICOLON
0x27, // KEY_APOSTROPHE 0x27, // KEY_APOSTROPHE
0x32, // KEY_GRAVE 0x32, // KEY_GRAVE
0x38, // KEY_LEFTSHIFT 0x38, // KEY_LEFTSHIFT
0x2A, // KEY_BACKSLASH 0x2A, // KEY_BACKSLASH
0x06, // KEY_Z 0x06, // KEY_Z
0x07, // KEY_X 0x07, // KEY_X
0x08, // KEY_C 0x08, // KEY_C
0x09, // KEY_V 0x09, // KEY_V
0x0B, // KEY_B 0x0B, // KEY_B
0x2D, // KEY_N 0x2D, // KEY_N
0x2E, // KEY_M 0x2E, // KEY_M
0x2B, // KEY_COMMA 0x2B, // KEY_COMMA
0x2F, // KEY_DOT 0x2F, // KEY_DOT
0x2C, // KEY_SLASH 0x2C, // KEY_SLASH
0x38, // KEY_RIGHTSHIFT 0x38, // KEY_RIGHTSHIFT
0x43, // KEY_KPASTERISK 0x43, // KEY_KPASTERISK
0x37, // KEY_LEFTALT 0x37, // KEY_LEFTALT
0x31, // KEY_SPACE 0x31, // KEY_SPACE
0x39, // KEY_CAPSLOCK 0x39, // KEY_CAPSLOCK
0x7A, // KEY_F1 0x7A, // KEY_F1
0x78, // KEY_F2 0x78, // KEY_F2
0x63, // KEY_F3 0x63, // KEY_F3
0x76, // KEY_F4 0x76, // KEY_F4
0x60, // KEY_F5 0x60, // KEY_F5
0x61, // KEY_F6 0x61, // KEY_F6
0x62, // KEY_F7 0x62, // KEY_F7
0x64, // KEY_F8 0x64, // KEY_F8
0x65, // KEY_F9 0x65, // KEY_F9
0x6D, // KEY_F10 0x6D, // KEY_F10
0x47, // KEY_NUMLOCK 0x47, // KEY_NUMLOCK
0x37, // KEY_SCROLLLOCK 0x37, // KEY_SCROLLLOCK
0x59, // KEY_KP7 0x59, // KEY_KP7
0x5B, // KEY_KP8 0x5B, // KEY_KP8
0x5C, // KEY_KP9 0x5C, // KEY_KP9
0x4E, // KEY_KPMINUS 0x4E, // KEY_KPMINUS
0x56, // KEY_KP4 0x56, // KEY_KP4
0x57, // KEY_KP5 0x57, // KEY_KP5
0x58, // KEY_KP6 0x58, // KEY_KP6
0x45, // KEY_KPPLUS 0x45, // KEY_KPPLUS
0x53, // KEY_KP1 0x53, // KEY_KP1
0x54, // KEY_KP2 0x54, // KEY_KP2
0x55, // KEY_KP3 0x55, // KEY_KP3
0x52, // KEY_KP0 0x52, // KEY_KP0
0x41, // KEY_KPDOT 0x41, // KEY_KPDOT
-1, -1,
-1, // KEY_ZENKAKUHANKAKU -1, // KEY_ZENKAKUHANKAKU
-1, // KEY_102ND -1, // KEY_102ND
0x67, // KEY_F11 0x67, // KEY_F11
0x6F, // KEY_F12 0x6F, // KEY_F12
-1, // KEY_RO -1, // KEY_RO
-1, // KEY_KATAKANA -1, // KEY_KATAKANA
-1, // KEY_HIRAGANA -1, // KEY_HIRAGANA
-1, // KEY_HENKAN -1, // KEY_HENKAN
-1, // KEY_KATAKANAHIRAGANA -1, // KEY_KATAKANAHIRAGANA
-1, // KEY_MUHENKAN -1, // KEY_MUHENKAN
-1, // KEY_KPJPCOMMA -1, // KEY_KPJPCOMMA
0x4C, // KEY_KPENTER 0x4C, // KEY_KPENTER
0x36, // KEY_RIGHTCTRL 0x36, // KEY_RIGHTCTRL
0x4B, // KEY_KPSLASH 0x4B, // KEY_KPSLASH
0x7F, // KEY_SYSRQ 0x7F, // KEY_SYSRQ
0x37, // KEY_RIGHTALT 0x37, // KEY_RIGHTALT
0x6E, // KEY_LINEFEED 0x6E, // KEY_LINEFEED
0x73, // KEY_HOME 0x73, // KEY_HOME
0x3E, // KEY_UP 0x3E, // KEY_UP
0x74, // KEY_PAGEUP 0x74, // KEY_PAGEUP
0x3B, // KEY_LEFT 0x3B, // KEY_LEFT
0x3C, // KEY_RIGHT 0x3C, // KEY_RIGHT
0x77, // KEY_END 0x77, // KEY_END
0x3D, // KEY_DOWN 0x3D, // KEY_DOWN
0x79, // KEY_PAGEDOWN 0x79, // KEY_PAGEDOWN
0x72, // KEY_INSERT 0x72, // KEY_INSERT
0x33, // KEY_DELETE 0x33, // KEY_DELETE
-1, // KEY_MACRO -1, // KEY_MACRO
-1, // KEY_MUTE -1, // KEY_MUTE
-1, // KEY_VOLUMEDOWN -1, // KEY_VOLUMEDOWN
-1, // KEY_VOLUMEUP -1, // KEY_VOLUMEUP
0x7F, // KEY_POWER /* SC System Power Down */ 0x7F, // KEY_POWER /* SC System Power Down */
0x51, // KEY_KPEQUAL 0x51, // KEY_KPEQUAL
0x4E, // KEY_KPPLUSMINUS 0x4E, // KEY_KPPLUSMINUS
-1, // KEY_PAUSE -1, // KEY_PAUSE
-1, // KEY_SCALE /* AL Compiz Scale (Expose) */ -1, // KEY_SCALE /* AL Compiz Scale (Expose) */
0x2B, // KEY_KPCOMMA 0x2B, // KEY_KPCOMMA
-1, // KEY_HANGEUL -1, // KEY_HANGEUL
-1, // KEY_HANJA -1, // KEY_HANJA
-1, // KEY_YEN -1, // KEY_YEN
0x3A, // KEY_LEFTMETA 0x3A, // KEY_LEFTMETA
0x3A, // KEY_RIGHTMETA 0x3A, // KEY_RIGHTMETA
-1 // KEY_COMPOSE -1 // KEY_COMPOSE
}; };
struct termios org_tio; struct termios org_tio;
struct fb_var_screeninfo orig_vinfo; struct fb_var_screeninfo orig_vinfo;
struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo; struct fb_fix_screeninfo finfo;
int pix_size, g_screen_mdepth, g_use_shmem = 1; int pix_size, g_screen_mdepth, g_use_shmem = 1;
#define MOUSE_LBTN_DOWN 0x01 #define MOUSE_LBTN_DOWN 0x01
#define MOUSE_MBTN_DOWN 0x02 #define MOUSE_MBTN_DOWN 0x02
#define MOUSE_RBTN_DOWN 0x04 #define MOUSE_RBTN_DOWN 0x04
#define MOUSE_LBTN_UP 0x00 #define MOUSE_LBTN_UP 0x00
#define MOUSE_MBTN_UP 0x00 #define MOUSE_MBTN_UP 0x00
#define MOUSE_RBTN_UP 0x00 #define MOUSE_RBTN_UP 0x00
#define MOUSE_BTN_ACTIVE 0x07 #define MOUSE_BTN_ACTIVE 0x07
#define UPDATE_INPUT_MOUSE 0x10 #define UPDATE_INPUT_MOUSE 0x10
#define MAX_EVDEV 8 #define MAX_EVDEV 8
char *fb_ptr, g_inputstate = 0; char *fb_ptr, g_inputstate = 0;
int evfd[MAX_EVDEV], evdevs, termfd, fbfd = 0; int evfd[MAX_EVDEV], evdevs, termfd, fbfd = 0;
/* /*
* Clean up * Clean up
*/ */
void xdriver_end(void) void xdriver_end(void) {
{ char c;
char c; static char xexit = 0;
static char xexit = 0; if (!xexit)
if (!xexit) {
// cleanup
munmap(fb_ptr, finfo.smem_len);
ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo);
close(fbfd);
if (termfd > 0)
{ {
// cleanup // Flush input
munmap(fb_ptr, finfo.smem_len); while (read(termfd, &c, 1) == 1);
ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo); ioctl(termfd, KDSETMODE, KD_TEXT);
close(fbfd); tcsetattr(termfd, TCSANOW, &org_tio);
if (termfd > 0) close(termfd);
{
// 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;
} }
fclose(stdout);
fclose(stderr);
while (evdevs--)
close(evfd[evdevs]);
xexit = 1;
}
} }
/* /*
* Init framebuffer and input * Init framebuffer and input
*/ */
void dev_video_init(void) void dev_video_init(void) {
{ int i;
int i; char evdevname[20];
char evdevname[20]; struct termios termio;
struct termios termio;
// Set graphics mode on console // Set graphics mode on console
if ((termfd = open("/dev/tty", O_RDWR)) < 0) if ((termfd = open("/dev/tty", O_RDWR)) < 0)
{ {
fprintf(stderr, "Error opening tty device.\n"); fprintf(stderr, "Error opening tty device.\n");
exit(-1); exit(-1);
} }
// Save input settings. // Save input settings.
tcgetattr(termfd, &termio); /* save current port settings */ tcgetattr(termfd, &termio); /* save current port settings */
memcpy(&org_tio, &termio, sizeof(struct termios)); memcpy(&org_tio, &termio, sizeof(struct termios));
ioctl(termfd, KDSETMODE, KD_GRAPHICS); ioctl(termfd, KDSETMODE, KD_GRAPHICS);
// Open the file for reading and writing // Open the file for reading and writing
if ((fbfd = open("/dev/fb0", O_RDWR)) < 0) if ((fbfd = open("/dev/fb0", O_RDWR)) < 0)
{ {
fprintf(stderr, "Error opening framebuffer device.\n"); fprintf(stderr, "Error opening framebuffer device.\n");
ioctl(termfd, KDSETMODE, KD_TEXT); ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1); exit(-1);
} }
// Get variable screen information // Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
{ {
fprintf(stderr, "Error reading variable screen information.\n"); fprintf(stderr, "Error reading variable screen information.\n");
ioctl(termfd, KDSETMODE, KD_TEXT); ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1); exit(-1);
} }
// Store for reset(copy vinfo to vinfo_orig) // Store for reset(copy vinfo to vinfo_orig)
memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo)); memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo));
// Change variable info // Change variable info
//vinfo.bits_per_pixel = 8; //vinfo.bits_per_pixel = 8;
// Change resolution // Change resolution
vinfo.xres = 640; vinfo.xres = 640;
vinfo.yres = 400; vinfo.yres = 400;
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
{ {
fprintf(stderr, "Error setting variable screen information (640x400x8).\n"); fprintf(stderr, "Error setting variable screen information (640x400x8).\n");
ioctl(termfd, KDSETMODE, KD_TEXT); ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1); exit(-1);
} }
// Get fixed screen information // Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
{ {
fprintf(stderr, "Error reading fixed screen information.\n"); fprintf(stderr, "Error reading fixed screen information.\n");
ioctl(termfd, KDSETMODE, KD_TEXT); ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1); exit(-1);
} }
// map fb to user mem // map fb to user mem
fb_ptr = (char*)mmap(0, fb_ptr = (char*)mmap(0,
finfo.smem_len, finfo.smem_len,
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
MAP_SHARED, MAP_SHARED,
fbfd, fbfd,
0); 0);
if ((int)fb_ptr == -1) if ((int)fb_ptr == -1)
{ {
printf("Failed to mmap framebuffer.\n"); printf("Failed to mmap framebuffer.\n");
ioctl(termfd, KDSETMODE, KD_TEXT); ioctl(termfd, KDSETMODE, KD_TEXT);
exit (-1); exit (-1);
} }
g_screen_depth = vinfo.bits_per_pixel; g_screen_depth = vinfo.bits_per_pixel;
g_screen_mdepth = g_screen_depth; g_screen_mdepth = g_screen_depth;
if (g_screen_depth > 8) if (g_screen_depth > 8)
g_screen_mdepth = 16; g_screen_mdepth = 16;
if (g_screen_depth > 16) if (g_screen_depth > 16)
g_screen_mdepth = 32; g_screen_mdepth = 32;
pix_size = g_screen_mdepth / 8; pix_size = g_screen_mdepth / 8;
if (vinfo.bits_per_pixel > 8) if (vinfo.bits_per_pixel > 8)
{ {
g_red_mask = (1 << vinfo.red.length) - 1; g_red_mask = (1 << vinfo.red.length) - 1;
g_green_mask = (1 << vinfo.green.length) - 1; g_green_mask = (1 << vinfo.green.length) - 1;
g_blue_mask = (1 << vinfo.blue.length) - 1; g_blue_mask = (1 << vinfo.blue.length) - 1;
g_red_left_shift = vinfo.red.offset; g_red_left_shift = vinfo.red.offset;
g_green_left_shift = vinfo.green.offset; g_green_left_shift = vinfo.green.offset;
g_blue_left_shift = vinfo.blue.offset; g_blue_left_shift = vinfo.blue.offset;
g_red_right_shift = 8 - vinfo.red.length; g_red_right_shift = 8 - vinfo.red.length;
g_green_right_shift = 8 - vinfo.green.length; g_green_right_shift = 8 - vinfo.green.length;
g_blue_right_shift = 8 - vinfo.blue.length; g_blue_right_shift = 8 - vinfo.blue.length;
} }
video_get_kimages(); video_get_kimages();
if (g_screen_depth > 8) if (g_screen_depth > 8)
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, g_screen_mdepth); video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, g_screen_mdepth);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
video_update_color_raw(i, g_lores_colors[i & 0xf]); video_update_color_raw(i, g_lores_colors[i & 0xf]);
g_a2palette_8to1624[i] = g_palette_8to1624[i]; g_a2palette_8to1624[i] = g_palette_8to1624[i];
} }
fclose(stdin); fclose(stdin);
freopen("gsport.log", "w+", stdout); freopen("gsport.log", "w+", stdout);
freopen("gsport.err", "w+", stderr); freopen("gsport.err", "w+", stderr);
termio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD; termio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD;
termio.c_iflag = IGNPAR; termio.c_iflag = IGNPAR;
termio.c_oflag = 0; termio.c_oflag = 0;
termio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */ termio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
termio.c_cc[VTIME] = 0; /* inter-character timer unused */ termio.c_cc[VTIME] = 0; /* inter-character timer unused */
termio.c_cc[VMIN] = 0; /* non-blocking read */ termio.c_cc[VMIN] = 0; /* non-blocking read */
tcsetattr(termfd, TCSANOW, &termio); tcsetattr(termfd, TCSANOW, &termio);
// Open input event devices // Open input event devices
for (evdevs = 0; evdevs < MAX_EVDEV; evdevs++) for (evdevs = 0; evdevs < MAX_EVDEV; evdevs++)
{ {
sprintf(evdevname, "/dev/input/event%c", evdevs + '0'); sprintf(evdevname, "/dev/input/event%c", evdevs + '0');
if ((evfd[evdevs] = open(evdevname, O_RDONLY|O_NONBLOCK)) < 0) if ((evfd[evdevs] = open(evdevname, O_RDONLY|O_NONBLOCK)) < 0)
break; break;
} }
g_video_act_margin_left = 0; g_video_act_margin_left = 0;
g_video_act_margin_right = 1; g_video_act_margin_right = 1;
g_video_act_margin_top = 0; g_video_act_margin_top = 0;
g_video_act_margin_bottom = 0; g_video_act_margin_bottom = 0;
} }
/* /*
* Colormap * Colormap
*/ */
__u16 cmapred[256], cmapgreen[256], cmapblue[256]; __u16 cmapred[256], cmapgreen[256], cmapblue[256];
int cmapstart, cmaplen, cmapdirty = 0; int cmapstart, cmaplen, cmapdirty = 0;
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) {
{ cmapred[col_num] = red | (red << 8);
cmapred[col_num] = red | (red << 8); cmapgreen[col_num] = green | (green << 8);
cmapgreen[col_num] = green | (green << 8); cmapblue[col_num] = blue | (blue << 8);
cmapblue[col_num] = blue | (blue << 8); if (cmapdirty == 0)
if (cmapdirty == 0) {
cmapstart = col_num;
cmaplen = 1;
cmapdirty = 1;
}
else
{
if (col_num < cmapstart)
{ {
cmapstart = col_num; cmaplen += cmapstart - col_num;
cmaplen = 1; cmapstart = col_num;
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;
} }
else if (col_num > cmapstart + cmaplen)
cmaplen = col_num - cmapstart + 1;
}
} }
void x_update_physical_colormap(void) void x_update_physical_colormap(void) {
{ struct fb_cmap fbcol;
struct fb_cmap fbcol; if (cmapdirty)
if (cmapdirty) {
{ cmapdirty = 0;
cmapdirty = 0; fbcol.start = cmapstart;
fbcol.start = cmapstart; fbcol.len = cmaplen;
fbcol.len = cmaplen; fbcol.red = cmapred;
fbcol.red = cmapred; fbcol.green = cmapgreen;
fbcol.green = cmapgreen; fbcol.blue = cmapblue;
fbcol.blue = cmapblue; fbcol.transp = NULL;
fbcol.transp = NULL; ioctl(fbfd, FBIOPUTCMAP, &fbcol);
ioctl(fbfd, FBIOPUTCMAP, &fbcol); }
}
} }
void show_xcolor_array(void) void show_xcolor_array(void) {
{
} }
/* /*
* Screen update * Screen update
*/ */
void x_get_kimage(Kimage *kimage_ptr) void x_get_kimage(Kimage *kimage_ptr) {
{ kimage_ptr->data_ptr = (byte *)malloc(kimage_ptr->width_req * kimage_ptr->height * kimage_ptr->mdepth / 8);
kimage_ptr->data_ptr = (byte *)malloc(kimage_ptr->width_req * kimage_ptr->height * kimage_ptr->mdepth / 8);
} }
void x_release_kimage(Kimage* kimage_ptr) void x_release_kimage(Kimage* kimage_ptr) {
{ if (kimage_ptr->data_ptr)
if (kimage_ptr->data_ptr) if (kimage_ptr->width_req != 640 || kimage_ptr->height != 400)
if (kimage_ptr->width_req != 640 || kimage_ptr->height != 400) free(kimage_ptr->data_ptr);
free(kimage_ptr->data_ptr); kimage_ptr->data_ptr = NULL;
kimage_ptr->data_ptr = NULL;
} }
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height) void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height) {
{ byte *src_ptr, *dst_ptr;
byte *src_ptr, *dst_ptr;
// Copy sub-image to framebuffer // Copy sub-image to framebuffer
dst_ptr = (byte *)fb_ptr + desty * finfo.line_length + destx * pix_size; 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; src_ptr = kimage_ptr->data_ptr + (srcy * kimage_ptr->width_act + srcx) * pix_size;
width *= pix_size; width *= pix_size;
while (height--) while (height--)
{ {
memcpy(dst_ptr, src_ptr, width); memcpy(dst_ptr, src_ptr, width);
dst_ptr += finfo.line_length; dst_ptr += finfo.line_length;
src_ptr += kimage_ptr->width_act * pix_size; src_ptr += kimage_ptr->width_act * pix_size;
} }
} }
void x_push_done(void) void x_push_done(void) {
{
} }
/* /*
* NOP routines * NOP routines
*/ */
void x_dialog_create_gsport_conf(const char *str) void x_dialog_create_gsport_conf(const char *str) {
{ // Just write the config file already...
// Just write the config file already... config_write_config_gsplus_file();
config_write_config_gsplus_file();
} }
int x_show_alert(int is_fatal, const char *str) int x_show_alert(int is_fatal, const char *str) {
{ // Not implemented yet
// Not implemented yet adb_all_keys_up();
adb_all_keys_up(); clear_fatal_logs();
clear_fatal_logs(); return 0;
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) int x_calc_ratio(float x, float y) {
{ return 1;
return 1;
} }
void clipboard_paste(void) void clipboard_paste(void) {
{
} }
int clipboard_get_char(void) int clipboard_get_char(void) {
{ return 0;
return 0;
} }
/* /*
* Input handling * Input handling
*/ */
void check_input_events(void) void check_input_events(void) {
{ struct input_event ev;
struct input_event ev; int i;
int i;
for (i = 0; i < evdevs; i++)
for (i = 0; i < evdevs; i++) // Check input events
// Check input events while (read(evfd[i], &ev, sizeof(struct input_event)) == sizeof(struct input_event))
while (read(evfd[i], &ev, sizeof(struct input_event)) == sizeof(struct input_event)) {
{ if (ev.type == EV_REL)
if (ev.type == EV_REL) {
{ if (ev.code == REL_X)
if (ev.code == REL_X) {
{ g_mouse_raw_x += ev.value;
g_mouse_raw_x += ev.value; if (g_mouse_raw_x < 0)
if (g_mouse_raw_x < 0) g_mouse_raw_x = 0;
g_mouse_raw_x = 0; if (g_mouse_raw_x > 639)
if (g_mouse_raw_x > 639) g_mouse_raw_x = 639;
g_mouse_raw_x = 639; }
} else // REL_Y
else // REL_Y {
{ g_mouse_raw_y += ev.value;
g_mouse_raw_y += ev.value; if (g_mouse_raw_y < 0)
if (g_mouse_raw_y < 0) g_mouse_raw_y = 0;
g_mouse_raw_y = 0; if (g_mouse_raw_y > 399)
if (g_mouse_raw_y > 399) g_mouse_raw_y = 399;
g_mouse_raw_y = 399; }
} g_inputstate |= UPDATE_INPUT_MOUSE;
g_inputstate |= UPDATE_INPUT_MOUSE; }
} else if (ev.type == EV_KEY)
else if (ev.type == EV_KEY) {
{ if (ev.code < 128)
if (ev.code < 128) {
{
#if 0 #if 0
if ((ev.code == KEY_F10) && SHIFT_DOWN) if ((ev.code == KEY_F10) && SHIFT_DOWN)
{ {
//quitEmulator(); //quitEmulator();
iwm_shut(); iwm_shut();
xdriver_end(); xdriver_end();
my_exit(1); my_exit(1);
} }
#endif #endif
if (keycode_to_a2code[ev.code] >= 0) if (keycode_to_a2code[ev.code] >= 0)
adb_physical_key_update(keycode_to_a2code[ev.code], !ev.value); adb_physical_key_update(keycode_to_a2code[ev.code], !ev.value);
} }
else if (ev.code == BTN_LEFT) else if (ev.code == BTN_LEFT)
{ {
g_inputstate = ev.value ? UPDATE_INPUT_MOUSE | MOUSE_LBTN_DOWN g_inputstate = ev.value ? UPDATE_INPUT_MOUSE | MOUSE_LBTN_DOWN
: UPDATE_INPUT_MOUSE | MOUSE_LBTN_UP; : UPDATE_INPUT_MOUSE | MOUSE_LBTN_UP;
} }
} }
else if (ev.type == EV_SYN) else if (ev.type == EV_SYN)
{ {
if (g_inputstate & UPDATE_INPUT_MOUSE) if (g_inputstate & UPDATE_INPUT_MOUSE)
update_mouse(g_mouse_raw_x, g_mouse_raw_y, g_inputstate & MOUSE_BTN_ACTIVE, MOUSE_BTN_ACTIVE); update_mouse(g_mouse_raw_x, g_mouse_raw_y, g_inputstate & MOUSE_BTN_ACTIVE, MOUSE_BTN_ACTIVE);
g_inputstate &= ~UPDATE_INPUT_MOUSE; g_inputstate &= ~UPDATE_INPUT_MOUSE;
} }
} }
} }
static void sig_bye(int signo) static void sig_bye(int signo) {
{ xdriver_end();
xdriver_end(); exit (-1);
exit (-1);
} }
/* /*
* Application entrypoint * Application entrypoint
*/ */
int main(int argc,char *argv[]) int main(int argc,char *argv[]) {
{ if (signal(SIGINT, sig_bye) == SIG_ERR)
if (signal(SIGINT, sig_bye) == SIG_ERR) exit(-1);
exit(-1); if (signal(SIGHUP, sig_bye) == SIG_ERR)
if (signal(SIGHUP, sig_bye) == SIG_ERR) exit(-1);
exit(-1); gsplusmain(argc, argv);
gsplusmain(argc, argv); xdriver_end();
xdriver_end(); return 0;
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 <stdio.h>
#include <time.h> #include <time.h>
#include <stdarg.h> #include <stdarg.h>
@ -5,37 +11,37 @@
#include "glog.h" #include "glog.h"
int glog(const char *s) { int glog(const char *s) {
time_t timer; time_t timer;
char buffer[26]; char buffer[26];
struct tm* tm_info; struct tm* tm_info;
time(&timer); time(&timer);
tm_info = localtime(&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 - %s\n", buffer, s); printf("%s - %s\n", buffer, s);
return 0; return 0;
} }
int glogf(const char *fmt, ...) { int glogf(const char *fmt, ...) {
time_t timer; time_t timer;
char buffer[26]; char buffer[26];
struct tm* tm_info; struct tm* tm_info;
time(&timer); time(&timer);
tm_info = localtime(&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_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vprintf(fmt, ap); vprintf(fmt, ap);
va_end(ap); va_end(ap);
fputc('\n', stdout); fputc('\n', stdout);
return 0; return 0;
} }

View File

@ -1,21 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey
This program is free software; you can redistribute it and/or modify it See COPYRIGHT.txt for Copyright information
under the terms of the GNU General Public License as published by the See LICENSE.txt for license (GPL v2)
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
*/
#include "defc.h" #include "defc.h"
#include "glog.h" #include "glog.h"
@ -42,7 +30,7 @@ int clipboard_get_char() { return 0; }
void clipboard_paste(void) { } void clipboard_paste(void) { }
void dev_video_init() { void dev_video_init() {
g_screen_depth = 24; g_screen_depth = 24;
g_screen_mdepth = 32; 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) 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Copyright (C) 2010 - 2011 by GSport contributors Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey See LICENSE.txt for license (GPL v2)
*/
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
*/
/* /*
* Copyright (C) 2002-2004 The DOSBox Team * 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #include "defc.h"
#include "glog.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_type1; /* in paddles.c */
extern int g_joystick_native_type2; /* 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_type; /* in paddles.c */
extern int g_joystick_type; extern int g_joystick_type;
extern int g_paddle_buttons; extern int g_paddle_buttons;
extern int g_paddle_val[]; extern int g_paddle_val[];
const char *g_joystick_dev = "/dev/input/js0"; /* default joystick dev file */ const char *g_joystick_dev = "/dev/input/js0"; /* default joystick dev file */
#define MAX_JOY_NAME 128 #define MAX_JOY_NAME 128
int g_joystick_native_fd = -1; int g_joystick_native_fd = -1;
int g_joystick_num_axes = 0; int g_joystick_num_axes = 0;
int g_joystick_num_buttons = 0; int g_joystick_num_buttons = 0;
int g_joystick_number = 0; // SDL2 int g_joystick_number = 0; // SDL2
int g_joystick_x_axis = 0; // SDL2 int g_joystick_x_axis = 0; // SDL2
int g_joystick_y_axis = 1; // SDL2 int g_joystick_y_axis = 1; // SDL2
int g_joystick_button_0 = 0; // SDL2 int g_joystick_button_0 = 0; // SDL2
int g_joystick_button_1 = 1; // SDL2 int g_joystick_button_1 = 1; // SDL2
int g_joystick_x2_axis = 2; // SDL2 int g_joystick_x2_axis = 2; // SDL2
int g_joystick_y2_axis = 3; // SDL2 int g_joystick_y2_axis = 3; // SDL2
int g_joystick_button_2 = 2; // SDL2 int g_joystick_button_2 = 2; // SDL2
int g_joystick_button_3 = 3; // SDL2 int g_joystick_button_3 = 3; // SDL2
#define JOY2SUPPORT #define JOY2SUPPORT
#if defined(HAVE_SDL) && !defined(JOYSTICK_DEFINED) #if defined(HAVE_SDL) && !defined(JOYSTICK_DEFINED)
# define JOYSTICK_DEFINED # define JOYSTICK_DEFINED
void void joystick_init() {
joystick_init()
{
int i; int i;
if( SDL_Init( SDL_INIT_JOYSTICK ) < 0 ) { 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 { } else {
glog("SDL2 joystick initialized"); glog("SDL2 joystick initialized");
} }
@ -70,16 +68,16 @@ joystick_init()
glog("No joysticks detected"); glog("No joysticks detected");
SDL_QuitSubSystem(SDL_INIT_JOYSTICK); SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
} else { } else {
// @todo: make controller configurable // @todo: make controller configurable
// @todo: add multiple controller support // @todo: add multiple controller support
gGameController = SDL_JoystickOpen( g_joystick_number ); gGameController = SDL_JoystickOpen( g_joystick_number );
if( gGameController == NULL ) { if( gGameController == NULL ) {
glogf( "Warning: Unable to open game controller! SDL Error: %s", SDL_GetError() ); glogf( "Warning: Unable to open game controller! SDL Error: %s", SDL_GetError() );
} }
} }
g_joystick_native_type = 2; g_joystick_native_type = 2;
g_joystick_native_type1 = 2; g_joystick_native_type1 = 2;
g_joystick_native_type2 = -1; g_joystick_native_type2 = -1;
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
g_paddle_val[i] = 180; g_paddle_val[i] = 180;
} }
@ -88,43 +86,39 @@ joystick_init()
joystick_update(0.0); joystick_update(0.0);
} }
void void joystick_update(double dcycs) {
joystick_update(double dcycs)
{
if (gGameController) { if (gGameController) {
SDL_JoystickUpdate(); SDL_JoystickUpdate();
g_paddle_val[0] = (int)SDL_JoystickGetAxis(gGameController, g_joystick_x_axis); // default is 0 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[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[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 g_paddle_val[3] = (int)SDL_JoystickGetAxis(gGameController, g_joystick_y2_axis); // default is 3
if (SDL_JoystickGetButton(gGameController, g_joystick_button_0)) { if (SDL_JoystickGetButton(gGameController, g_joystick_button_0)) {
g_paddle_buttons = g_paddle_buttons | 1; g_paddle_buttons = g_paddle_buttons | 1;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~1); g_paddle_buttons = g_paddle_buttons & (~1);
} }
if (SDL_JoystickGetButton(gGameController, g_joystick_button_1)) { if (SDL_JoystickGetButton(gGameController, g_joystick_button_1)) {
g_paddle_buttons = g_paddle_buttons | 2; g_paddle_buttons = g_paddle_buttons | 2;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~2); g_paddle_buttons = g_paddle_buttons & (~2);
} }
if (SDL_JoystickGetButton(gGameController, g_joystick_button_2)) { if (SDL_JoystickGetButton(gGameController, g_joystick_button_2)) {
g_paddle_buttons = g_paddle_buttons | 4; g_paddle_buttons = g_paddle_buttons | 4;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~4); g_paddle_buttons = g_paddle_buttons & (~4);
} }
if (SDL_JoystickGetButton(gGameController, g_joystick_button_3)) { if (SDL_JoystickGetButton(gGameController, g_joystick_button_3)) {
g_paddle_buttons = g_paddle_buttons | 8; g_paddle_buttons = g_paddle_buttons | 8;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~8); g_paddle_buttons = g_paddle_buttons & (~8);
} }
paddle_update_trigger_dcycs(dcycs); paddle_update_trigger_dcycs(dcycs);
} }
} }
void void joystick_update_buttons() {
joystick_update_buttons()
{
} }
void joystick_shut() { void joystick_shut() {
@ -139,202 +133,190 @@ void joystick_shut() {
#if defined(__linux__) && !defined(JOYSTICK_DEFINED) #if defined(__linux__) && !defined(JOYSTICK_DEFINED)
# define JOYSTICK_DEFINED # define JOYSTICK_DEFINED
void void joystick_init() {
joystick_init() char joy_name[MAX_JOY_NAME];
{ int version;
char joy_name[MAX_JOY_NAME]; int fd;
int version; int i;
int fd;
int i;
fd = open(g_joystick_dev, O_RDONLY | O_NONBLOCK); fd = open(g_joystick_dev, O_RDONLY | O_NONBLOCK);
if(fd < 0) { if(fd < 0) {
printf("Unable to open joystick dev file: %s, errno: %d\n", printf("Unable to open joystick dev file: %s, errno: %d\n",
g_joystick_dev, errno); g_joystick_dev, errno);
printf("Defaulting to mouse joystick\n"); printf("Defaulting to mouse joystick\n");
return; return;
} }
strcpy(&joy_name[0], "Unknown Joystick"); strcpy(&joy_name[0], "Unknown Joystick");
version = 0x800; version = 0x800;
ioctl(fd, JSIOCGNAME(MAX_JOY_NAME), &joy_name[0]); ioctl(fd, JSIOCGNAME(MAX_JOY_NAME), &joy_name[0]);
ioctl(fd, JSIOCGAXES, &g_joystick_num_axes); ioctl(fd, JSIOCGAXES, &g_joystick_num_axes);
ioctl(fd, JSIOCGBUTTONS, &g_joystick_num_buttons); ioctl(fd, JSIOCGBUTTONS, &g_joystick_num_buttons);
ioctl(fd, JSIOCGVERSION, &version); ioctl(fd, JSIOCGVERSION, &version);
printf("Detected joystick: %s [%d axes, %d buttons vers: %08x]\n", printf("Detected joystick: %s [%d axes, %d buttons vers: %08x]\n",
joy_name, g_joystick_num_axes, g_joystick_num_buttons, joy_name, g_joystick_num_axes, g_joystick_num_buttons,
version); version);
g_joystick_native_type1 = 1; g_joystick_native_type1 = 1;
g_joystick_native_type2 = -1; g_joystick_native_type2 = -1;
g_joystick_native_fd = fd; g_joystick_native_fd = fd;
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767; g_paddle_val[i] = 32767;
} }
g_paddle_buttons = 0xc; g_paddle_buttons = 0xc;
joystick_update(0.0); joystick_update(0.0);
} }
/* joystick_update_linux() called from paddles.c. Update g_paddle_val[] */ /* joystick_update_linux() called from paddles.c. Update g_paddle_val[] */
/* and g_paddle_buttons with current information */ /* and g_paddle_buttons with current information */
void void joystick_update(double dcycs) {
joystick_update(double dcycs) struct js_event js; /* the linux joystick event record */
{ int mask;
struct js_event js; /* the linux joystick event record */ int val;
int mask; int num;
int val; int type;
int num; int ret;
int type; int len;
int ret; int i;
int len;
int i;
/* suck up to 20 events, then give up */ /* suck up to 20 events, then give up */
len = sizeof(struct js_event); len = sizeof(struct js_event);
for(i = 0; i < 20; i++) { for(i = 0; i < 20; i++) {
ret = read(g_joystick_native_fd, &js, len); ret = read(g_joystick_native_fd, &js, len);
if(ret != len) { if(ret != len) {
/* just get out */ /* just get out */
break; break;
} }
type = js.type & ~JS_EVENT_INIT; type = js.type & ~JS_EVENT_INIT;
val = js.value; val = js.value;
num = js.number & 3; /* clamp to 0-3 */ num = js.number & 3; /* clamp to 0-3 */
switch(type) { switch(type) {
case JS_EVENT_BUTTON: case JS_EVENT_BUTTON:
mask = 1 << num; mask = 1 << num;
if(val) { if(val) {
val = mask; val = mask;
} }
g_paddle_buttons = (g_paddle_buttons & ~mask) | val; g_paddle_buttons = (g_paddle_buttons & ~mask) | val;
break; break;
case JS_EVENT_AXIS: case JS_EVENT_AXIS:
/* val is -32767 to +32767 */ /* val is -32767 to +32767 */
g_paddle_val[num] = val; g_paddle_val[num] = val;
break; break;
} }
} }
// if(i > 0) { // if(i > 0) {
// Note from Dave Schmenk: paddle_update_trigger_dcycles(dcycs) always has to be called to keep the triggers current. // 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 void joystick_update_buttons() {
joystick_update_buttons()
{
} }
#endif /* LINUX */ #endif /* LINUX */
#if defined(_WIN32) && !defined(JOYSTICK_DEFINED) #if defined(_WIN32) && !defined(JOYSTICK_DEFINED)
# define JOYSTICK_DEFINED # define JOYSTICK_DEFINED
void void joystick_init() {
joystick_init() JOYINFO info;
{ JOYCAPS joycap;
JOYINFO info; MMRESULT ret1, ret2;
JOYCAPS joycap; int i;
MMRESULT ret1, ret2;
int i;
// Check that there is a joystick device // Check that there is a joystick device
if(joyGetNumDevs() <= 0) { if(joyGetNumDevs() <= 0) {
glog("No joystick hardware detected"); glog("No joystick hardware detected");
g_joystick_native_type1 = -1; g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1; g_joystick_native_type2 = -1;
return; return;
} }
g_joystick_native_type1 = -1; g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1; g_joystick_native_type2 = -1;
// Check that at least joystick 1 or joystick 2 is available // Check that at least joystick 1 or joystick 2 is available
ret1 = joyGetPos(JOYSTICKID1, &info); ret1 = joyGetPos(JOYSTICKID1, &info);
ret2 = joyGetDevCaps(JOYSTICKID1, &joycap, sizeof(joycap)); ret2 = joyGetDevCaps(JOYSTICKID1, &joycap, sizeof(joycap));
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) { if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_joystick_native_type1 = JOYSTICKID1; g_joystick_native_type1 = JOYSTICKID1;
printf("Joystick #1 = %s\n", joycap.szPname); printf("Joystick #1 = %s\n", joycap.szPname);
g_joystick_native_type = JOYSTICKID1; g_joystick_native_type = JOYSTICKID1;
} }
ret1 = joyGetPos(JOYSTICKID2, &info); ret1 = joyGetPos(JOYSTICKID2, &info);
ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap)); ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap));
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) { if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_joystick_native_type2 = JOYSTICKID2; g_joystick_native_type2 = JOYSTICKID2;
printf("Joystick #2 = %s\n", joycap.szPname); printf("Joystick #2 = %s\n", joycap.szPname);
if(g_joystick_native_type < 0) { if(g_joystick_native_type < 0) {
g_joystick_native_type = JOYSTICKID2; g_joystick_native_type = JOYSTICKID2;
} }
} }
if (g_joystick_native_type1<0 && g_joystick_native_type2 <0) { if (g_joystick_native_type1<0 && g_joystick_native_type2 <0) {
glog("No joystick is attached"); glog("No joystick is attached");
return; return;
} }
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767; g_paddle_val[i] = 32767;
} }
g_paddle_buttons = 0xc; g_paddle_buttons = 0xc;
joystick_update(0.0); joystick_update(0.0);
} }
void void joystick_update(double dcycs) {
joystick_update(double dcycs) JOYCAPS joycap;
{ JOYINFO info;
JOYCAPS joycap; UINT id;
JOYINFO info; MMRESULT ret1, ret2;
UINT id;
MMRESULT ret1, ret2;
id = g_joystick_native_type; id = g_joystick_native_type;
ret1 = joyGetDevCaps(id, &joycap, sizeof(joycap)); ret1 = joyGetDevCaps(id, &joycap, sizeof(joycap));
ret2 = joyGetPos(id, &info); ret2 = joyGetPos(id, &info);
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) { if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 32768 / g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 32768 /
(joycap.wXmax - joycap.wXmin); (joycap.wXmax - joycap.wXmin);
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 32768 / g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 32768 /
(joycap.wYmax - joycap.wYmin); (joycap.wYmax - joycap.wYmin);
if(info.wButtons & JOY_BUTTON1) { if(info.wButtons & JOY_BUTTON1) {
g_paddle_buttons = g_paddle_buttons | 1; g_paddle_buttons = g_paddle_buttons | 1;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~1); g_paddle_buttons = g_paddle_buttons & (~1);
} }
if(info.wButtons & JOY_BUTTON2) { if(info.wButtons & JOY_BUTTON2) {
g_paddle_buttons = g_paddle_buttons | 2; g_paddle_buttons = g_paddle_buttons | 2;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~2); g_paddle_buttons = g_paddle_buttons & (~2);
} }
paddle_update_trigger_dcycs(dcycs); paddle_update_trigger_dcycs(dcycs);
} }
} }
void void joystick_update_buttons() {
joystick_update_buttons() JOYINFOEX info;
{ UINT id;
JOYINFOEX info;
UINT id;
id = g_joystick_native_type; id = g_joystick_native_type;
info.dwSize = sizeof(JOYINFOEX); info.dwSize = sizeof(JOYINFOEX);
info.dwFlags = JOY_RETURNBUTTONS; info.dwFlags = JOY_RETURNBUTTONS;
if(joyGetPosEx(id, &info) == JOYERR_NOERROR) { if(joyGetPosEx(id, &info) == JOYERR_NOERROR) {
if(info.dwButtons & JOY_BUTTON1) { if(info.dwButtons & JOY_BUTTON1) {
g_paddle_buttons = g_paddle_buttons | 1; g_paddle_buttons = g_paddle_buttons | 1;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~1); g_paddle_buttons = g_paddle_buttons & (~1);
} }
if(info.dwButtons & JOY_BUTTON2) { if(info.dwButtons & JOY_BUTTON2) {
g_paddle_buttons = g_paddle_buttons | 2; g_paddle_buttons = g_paddle_buttons | 2;
} else { } else {
g_paddle_buttons = g_paddle_buttons & (~2); g_paddle_buttons = g_paddle_buttons & (~2);
} }
} }
} }
#endif #endif
@ -344,31 +326,24 @@ joystick_update_buttons()
#ifndef JOYSTICK_DEFINED #ifndef JOYSTICK_DEFINED
/* stubs for the routines */ /* stubs for the routines */
void void joystick_init() {
joystick_init() g_joystick_native_type1 = -1;
{ g_joystick_native_type2 = -1;
g_joystick_native_type1 = -1; g_joystick_native_type = -1;
g_joystick_native_type2 = -1;
g_joystick_native_type = -1;
} }
void void joystick_update(double dcycs) {
joystick_update(double dcycs) int i;
{
int i;
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767; g_paddle_val[i] = 32767;
} }
g_paddle_buttons = 0xc; g_paddle_buttons = 0xc;
} }
void void joystick_update_buttons() {
joystick_update_buttons()
{
} }
void joystick_shut() void joystick_shut() {
{
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#ifdef ACTIVEIPHONE #ifdef ACTIVEIPHONE
#include <CoreGraphics/CGContext.h> #include <CoreGraphics/CGContext.h>
@ -21,30 +21,30 @@
#include "protos_macdriver.h" #include "protos_macdriver.h"
word32 g_mac_shift_control_state = 0; word32 g_mac_shift_control_state = 0;
int macUsingCoreGraphics=0; int macUsingCoreGraphics=0;
// Coregraphics context // Coregraphics context
CGContextRef offscreenContext = NULL; CGContextRef offscreenContext = NULL;
char * bitmapData=NULL; char * bitmapData=NULL;
int bitmapByteCount; int bitmapByteCount;
int bitmapBytesPerRow; int bitmapBytesPerRow;
#ifdef ENABLEQD #ifdef ENABLEQD
WindowRef g_main_window; WindowRef g_main_window;
CGrafPtr mac_window_port; CGrafPtr mac_window_port;
#endif #endif
char *g_clipboard = 0x00; char *g_clipboard = 0x00;
int g_clipboard_pos; int g_clipboard_pos;
extern Kimage g_mainwin_kimage; extern Kimage g_mainwin_kimage;
int g_use_shmem = 0; int g_use_shmem = 0;
extern int Verbose; extern int Verbose;
@ -67,8 +67,8 @@ extern int g_send_sound_to_file;
extern int g_config_control_panel; extern int g_config_control_panel;
int g_auto_repeat_on = -1; int g_auto_repeat_on = -1;
int g_x_shift_control_state = 0; int g_x_shift_control_state = 0;
extern int Max_color_size; extern int Max_color_size;
@ -76,8 +76,8 @@ extern int Max_color_size;
extern word32 g_palette_8to1624[256]; extern word32 g_palette_8to1624[256];
extern word32 g_a2palette_8to1624[256]; extern word32 g_a2palette_8to1624[256];
int g_alt_left_up = 1; int g_alt_left_up = 1;
int g_alt_right_up = 1; int g_alt_right_up = 1;
extern word32 g_full_refresh_needed; extern word32 g_full_refresh_needed;
@ -100,442 +100,413 @@ int g_upd_count = 0;
void void update_window(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;
g_upd_count++; // OG Not needed
if(g_upd_count > 250) { /*
g_upd_count = 0; 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 void mac_update_modifiers(word32 state) {
mac_update_modifiers(word32 state)
{
#ifndef ACTIVEIPHONE #ifndef ACTIVEIPHONE
word32 state_xor; word32 state_xor;
int is_up; int is_up;
state = state & ( state = state & (
cmdKey | controlKey | cmdKey | controlKey |
shiftKey | alphaLock | optionKey shiftKey | alphaLock | optionKey
); );
state_xor = g_mac_shift_control_state ^ state; state_xor = g_mac_shift_control_state ^ state;
is_up = 0; is_up = 0;
if(state_xor & controlKey) { if(state_xor & controlKey) {
is_up = ((state & controlKey) == 0); is_up = ((state & controlKey) == 0);
adb_physical_key_update(0x36, is_up); adb_physical_key_update(0x36, is_up);
} }
if(state_xor & alphaLock) { if(state_xor & alphaLock) {
is_up = ((state & alphaLock) == 0); is_up = ((state & alphaLock) == 0);
adb_physical_key_update(0x39, is_up); adb_physical_key_update(0x39, is_up);
} }
if(state_xor & shiftKey) { if(state_xor & shiftKey) {
is_up = ((state & shiftKey) == 0); is_up = ((state & shiftKey) == 0);
adb_physical_key_update(0x38, is_up); adb_physical_key_update(0x38, is_up);
} }
if(state_xor & cmdKey) { if(state_xor & cmdKey) {
is_up = ((state & cmdKey) == 0); is_up = ((state & cmdKey) == 0);
adb_physical_key_update(0x37, is_up); adb_physical_key_update(0x37, is_up);
} }
if(state_xor & optionKey) { if(state_xor & optionKey) {
is_up = ((state & optionKey) == 0); is_up = ((state & optionKey) == 0);
adb_physical_key_update(0x3a, is_up); adb_physical_key_update(0x3a, is_up);
} }
#endif #endif
g_mac_shift_control_state = state; g_mac_shift_control_state = state;
} }
void void x_update_color(int col_num, int red, int green, int blue, word32 rgb) {
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
{
} }
void void x_update_physical_colormap() {
x_update_physical_colormap()
{
} }
void void show_xcolor_array() {
show_xcolor_array() int i;
{
int i;
for(i = 0; i < 256; i++) { for(i = 0; i < 256; i++) {
printf("%02x: %08x\n", i, g_palette_8to1624[i]); printf("%02x: %08x\n", i, g_palette_8to1624[i]);
} }
} }
void void x_get_kimage(Kimage *kimage_ptr) {
x_get_kimage(Kimage *kimage_ptr)
{
#ifdef ENABLEQD #ifdef ENABLEQD
PixMapHandle pixmap_handle; PixMapHandle pixmap_handle;
GWorldPtr world; GWorldPtr world;
Rect world_rect; Rect world_rect;
OSStatus err; OSStatus err;
#endif #endif
word32 *wptr; word32 *wptr;
byte *ptr; byte *ptr;
int row_bytes; int row_bytes;
int width; int width;
int height; int height;
int depth, mdepth; int depth, mdepth;
int size; int size;
width = kimage_ptr->width_req; width = kimage_ptr->width_req;
height = kimage_ptr->height; height = kimage_ptr->height;
depth = kimage_ptr->depth; depth = kimage_ptr->depth;
mdepth = kimage_ptr->mdepth; mdepth = kimage_ptr->mdepth;
size = 0; size = 0;
if(depth == g_screen_depth) if(depth == g_screen_depth)
{ {
if (!macUsingCoreGraphics) if (!macUsingCoreGraphics)
{ {
#ifdef ENABLEQD #ifdef ENABLEQD
SetRect(&world_rect, 0, 0, width, height); SetRect(&world_rect, 0, 0, width, height);
err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0); err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0);
pixmap_handle = GetGWorldPixMap(world); pixmap_handle = GetGWorldPixMap(world);
err = LockPixels(pixmap_handle); err = LockPixels(pixmap_handle);
ptr = (byte *)GetPixBaseAddr(pixmap_handle); ptr = (byte *)GetPixBaseAddr(pixmap_handle);
row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff); row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff);
kimage_ptr->width_act = row_bytes / (mdepth >> 3); 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("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); mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",(int)(*pixmap_handle)->baseAddr,(*pixmap_handle)->rowBytes,(*pixmap_handle)->pixelType);
wptr = (word32 *)(*pixmap_handle); 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]); 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->dev_handle = pixmap_handle;
kimage_ptr->data_ptr = ptr; kimage_ptr->data_ptr = ptr;
#endif #endif
} }
else 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 {
/* allocate buffers for video.c to draw into */
kimage_ptr->width_act = width;
kimage_ptr->width_act = width ; size = height* kimage_ptr->width_act * mdepth >> 3;
size = height* kimage_ptr->width_act * mdepth >> 3 ; ptr = (byte *)malloc(size);
ptr = (byte *)malloc(size);
if(ptr == 0) { if(ptr == 0) {
mac_printf("malloc for data fail, mdepth:%d\n", mdepth); mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
exit(2); exit(2);
} }
kimage_ptr->data_ptr = ptr; kimage_ptr->data_ptr = ptr;
kimage_ptr->dev_handle = (void *)-1; kimage_ptr->dev_handle = (void *)-1;
} }
}
else {
mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr, /* allocate buffers for video.c to draw into */
kimage_ptr->dev_handle, kimage_ptr->data_ptr, 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);
}
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 #ifdef ENABLEQD
PixMapHandle pixmap_backbuffer=NULL; PixMapHandle pixmap_backbuffer=NULL;
GWorldPtr backbuffer=NULL; GWorldPtr backbuffer=NULL;
#endif #endif
void void dev_video_init() {
dev_video_init() int lores_col;
{ int i;
int lores_col;
int i;
printf("Preparing graphics system\n"); printf("Preparing graphics system\n");
// OG Create backbuffer // OG Create backbuffer
if (!macUsingCoreGraphics) if (!macUsingCoreGraphics)
{ {
#ifdef ENABLEQD #ifdef ENABLEQD
Rect r; Rect r;
SetRect(&r, 0, 0, 704, 462); SetRect(&r, 0, 0, 704, 462);
QDErr err = NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0); QDErr err = NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0);
pixmap_backbuffer = GetGWorldPixMap(backbuffer); pixmap_backbuffer = GetGWorldPixMap(backbuffer);
#endif #endif
} }
else 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
}
int pixelsWide = 704;
video_get_kimages(); int pixelsHigh = 462;
bitmapBytesPerRow = (pixelsWide * 4); // 1
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
if(g_screen_depth != 8) { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Get g_mainwin_kimage bitmapData = (char*)malloc( bitmapByteCount ); // 3
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, if (bitmapData == NULL)
g_screen_mdepth); {
} 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++) { CGContextSetRGBFillColor (offscreenContext, 1, 0.5, 0.5, 1);
lores_col = g_lores_colors[i & 0xf]; CGContextFillRect (offscreenContext, CGRectMake (0,0, 704, 462 ));
video_update_color_raw(i, lores_col);
g_a2palette_8to1624[i] = g_palette_8to1624[i];
}
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 void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height) {
int width, int height) int i;
{
int i;
if (!macUsingCoreGraphics) if (!macUsingCoreGraphics)
{ {
#ifdef ENABLEQD #ifdef ENABLEQD
PixMapHandle pixmap_handle; PixMapHandle pixmap_handle;
Rect src_rect, dest_rect; Rect src_rect, dest_rect;
CGrafPtr window_port; CGrafPtr window_port;
pixmap_handle = (PixMapHandle)kimage_ptr->dev_handle; pixmap_handle = (PixMapHandle)kimage_ptr->dev_handle;
SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height); SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height);
SetRect(&dest_rect, destx, desty, destx + width, desty + height); SetRect(&dest_rect, destx, desty, destx + width, desty + height);
#ifndef ACTIVEGSPLUGIN #ifndef ACTIVEGSPLUGIN
SetPortWindowPort(g_main_window); SetPortWindowPort(g_main_window);
window_port = GetWindowPort(g_main_window); window_port = GetWindowPort(g_main_window);
CopyBits( (BitMap *)(*pixmap_handle), CopyBits( (BitMap *)(*pixmap_handle),
GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect, GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect,
srcCopy, NULL); srcCopy, NULL);
#else // !ACTIVEGSPLUGIN #else // !ACTIVEGSPLUGIN
// OG Write to the back buffer instead of the display window // OG Write to the back buffer instead of the display window
window_port = mac_window_port ; window_port = mac_window_port;
SetGWorld(backbuffer,NULL); SetGWorld(backbuffer,NULL);
CopyBits( (BitMap *)(*pixmap_handle), CopyBits( (BitMap *)(*pixmap_handle),
GetPortBitMapForCopyBits(backbuffer), &src_rect, &dest_rect, GetPortBitMapForCopyBits(backbuffer), &src_rect, &dest_rect,
srcCopy, NULL); srcCopy, NULL);
#endif // ACTIVEGSPLUGIN #endif // ACTIVEGSPLUGIN
#endif #endif
} }
else 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;
} 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 void x_auto_repeat_on(int must) {
x_auto_repeat_on(int must)
{
} }
void void x_auto_repeat_off(int must) {
x_auto_repeat_off(int must)
{
} }
void void x_hide_pointer(int do_hide) {
x_hide_pointer(int do_hide)
{
#ifdef ENABLEQD #ifdef ENABLEQD
if(do_hide) { if(do_hide) {
HideCursor(); HideCursor();
} else { } else {
ShowCursor(); ShowCursor();
} }
#endif #endif
} }
void void update_main_window_size() {
update_main_window_size()
{
#ifdef ENABLEQD #ifdef ENABLEQD
Rect win_rect; Rect win_rect;
int width, height; int width, height;
int left, excess_height; int left, excess_height;
int top, bottom; int top, bottom;
GetPortBounds(GetWindowPort(g_main_window), &win_rect); GetPortBounds(GetWindowPort(g_main_window), &win_rect);
width = win_rect.right - win_rect.left; width = win_rect.right - win_rect.left;
height = win_rect.bottom - win_rect.top; height = win_rect.bottom - win_rect.top;
g_video_act_width = width; g_video_act_width = width;
g_video_act_height = height; g_video_act_height = height;
left = MAX(0, (width - A2_WINDOW_WIDTH) / 2); left = MAX(0, (width - A2_WINDOW_WIDTH) / 2);
left = MIN(left, BASE_MARGIN_LEFT); left = MIN(left, BASE_MARGIN_LEFT);
g_video_act_margin_left = left; g_video_act_margin_left = left;
g_video_act_margin_right = left; g_video_act_margin_right = left;
excess_height = (height - A2_WINDOW_HEIGHT) / 2; excess_height = (height - A2_WINDOW_HEIGHT) / 2;
bottom = MAX(0, excess_height / 2); // No less than 0 bottom = MAX(0, excess_height / 2); // No less than 0
bottom = MIN(BASE_MARGIN_BOTTOM, bottom); // No more than 30 bottom = MIN(BASE_MARGIN_BOTTOM, bottom); // No more than 30
g_video_act_margin_bottom = bottom; g_video_act_margin_bottom = bottom;
excess_height -= bottom; excess_height -= bottom;
top = MAX(0, excess_height); top = MAX(0, excess_height);
top = MIN(BASE_MARGIN_TOP, top); top = MIN(BASE_MARGIN_TOP, top);
g_video_act_margin_top = top; g_video_act_margin_top = top;
#endif #endif
} }
// OG Adding release // OG Adding release
void x_release_kimage(Kimage* kimage_ptr) void x_release_kimage(Kimage* kimage_ptr) {
{ if (kimage_ptr->dev_handle == (void*)-1)
if (kimage_ptr->dev_handle == (void*)-1) {
{ free(kimage_ptr->data_ptr);
free(kimage_ptr->data_ptr); kimage_ptr->data_ptr = NULL;
kimage_ptr->data_ptr = NULL; }
} else
else {
{ if (!macUsingCoreGraphics)
if (!macUsingCoreGraphics) {
{
#ifdef ENABLEQD #ifdef ENABLEQD
UnlockPixels((PixMapHandle)kimage_ptr->dev_handle); UnlockPixels((PixMapHandle)kimage_ptr->dev_handle);
kimage_ptr->dev_handle = NULL; kimage_ptr->dev_handle = NULL;
DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2); DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2);
kimage_ptr->dev_handle2 = NULL; kimage_ptr->dev_handle2 = NULL;
#endif #endif
} }
} }
} }
// OG Addding ratio // OG Addding ratio
int x_calc_ratio(float x,float y) int x_calc_ratio(float x,float y) {
{ return 1;
return 1;
} }
void void clipboard_paste(void) {
clipboard_paste(void)
{
#define CHUNK_SIZE 1024 #define CHUNK_SIZE 1024
char buffer[CHUNK_SIZE]; char buffer[CHUNK_SIZE];
int bufsize = 1; int bufsize = 1;
void *expanding_buffer = 0x00; void *expanding_buffer = 0x00;
if (g_clipboard) if (g_clipboard)
{ {
g_clipboard_pos = 0; g_clipboard_pos = 0;
free(g_clipboard); free(g_clipboard);
g_clipboard = 0x00; g_clipboard = 0x00;
} }
FILE *pipe = popen("pbpaste", "r"); FILE *pipe = popen("pbpaste", "r");
if (pipe) if (pipe)
{ {
expanding_buffer = calloc(CHUNK_SIZE+1,1); expanding_buffer = calloc(CHUNK_SIZE+1,1);
bufsize = CHUNK_SIZE; bufsize = CHUNK_SIZE;
while (!feof(pipe)) while (!feof(pipe))
{ {
if (fgets(buffer, CHUNK_SIZE, pipe) != NULL) if (fgets(buffer, CHUNK_SIZE, pipe) != NULL)
{ {
while (strlen((char*)expanding_buffer) + strlen(buffer) > bufsize) while (strlen((char*)expanding_buffer) + strlen(buffer) > bufsize)
{ {
bufsize += CHUNK_SIZE + 1; bufsize += CHUNK_SIZE + 1;
expanding_buffer = realloc(expanding_buffer, bufsize); expanding_buffer = realloc(expanding_buffer, bufsize);
} }
/* Skip the leading return character when this is the first line in the paste buffer */ /* Skip the leading return character when this is the first line in the paste buffer */
if (strlen((char*)expanding_buffer) > 0) if (strlen((char*)expanding_buffer) > 0)
strcat((char*)expanding_buffer,"\r"); strcat((char*)expanding_buffer,"\r");
strncat((char*)expanding_buffer,buffer,strlen(buffer)); strncat((char*)expanding_buffer,buffer,strlen(buffer));
g_clipboard = (char*)expanding_buffer; g_clipboard = (char*)expanding_buffer;
} }
} }
} }
} }
int clipboard_get_char(void) int clipboard_get_char(void) {
{ if (!g_clipboard)
if (!g_clipboard) return 0;
return 0; if (g_clipboard[g_clipboard_pos] == '\n')
if (g_clipboard[g_clipboard_pos] == '\n') g_clipboard_pos++;
g_clipboard_pos++; if (g_clipboard[g_clipboard_pos] == '\0')
if (g_clipboard[g_clipboard_pos] == '\0') return 0;
return 0; return g_clipboard[g_clipboard_pos++] | 0x80;
return g_clipboard[g_clipboard_pos++] | 0x80;
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #include "defc.h"
@ -19,11 +19,11 @@ int mac_send_audio(byte *ptr, int in_size) {}
#include "sound.h" #include "sound.h"
#include <unistd.h> #include <unistd.h>
#define MACSND_REBUF_SIZE (64*1024) #define MACSND_REBUF_SIZE (64*1024)
#define MACSND_QUANTA 512 #define MACSND_QUANTA 512
/* MACSND_QUANTA must be >= 128 and a power of 2 */ /* 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_ptr;
volatile word32 *g_macsnd_rebuf_cur; volatile word32 *g_macsnd_rebuf_cur;
volatile int g_macsnd_playing = 0; volatile int g_macsnd_playing = 0;
@ -35,124 +35,116 @@ extern word32 *g_sound_shm_addr;
extern int g_sound_size; extern int g_sound_size;
SndChannelPtr g_snd_channel_ptr; SndChannelPtr g_snd_channel_ptr;
ExtSoundHeader g_snd_hdr; ExtSoundHeader g_snd_hdr;
SndCommand g_snd_cmd; SndCommand g_snd_cmd;
void void mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd) {
mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd) OSStatus err;
{ int samps;
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; samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur;
if(samps < 0) { if(samps < 0) {
samps += MACSND_REBUF_SIZE; samps += MACSND_REBUF_SIZE;
} }
samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples
if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) { if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) - samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) -
g_macsnd_rebuf_cur; g_macsnd_rebuf_cur;
} }
if(samps > 0) { if(samps > 0) {
g_macsnd_playing = 1; g_macsnd_playing = 1;
g_snd_hdr.numFrames = samps; g_snd_hdr.numFrames = samps;
g_snd_hdr.loopEnd = samps; g_snd_hdr.loopEnd = samps;
g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur; // OG Cast from byte* to ,char* g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur; // OG Cast from byte* to ,char*
g_snd_cmd.cmd = bufferCmd; g_snd_cmd.cmd = bufferCmd;
g_snd_cmd.param1 = 0; g_snd_cmd.param1 = 0;
g_snd_cmd.param2 = (long) &g_snd_hdr; g_snd_cmd.param2 = (long) &g_snd_hdr;
g_macsnd_rebuf_cur += samps; g_macsnd_rebuf_cur += samps;
if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) { if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
g_macsnd_rebuf_cur -= 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 // And set-up callback
g_snd_cmd.cmd = callBackCmd; g_snd_cmd.cmd = callBackCmd;
g_snd_cmd.param1 = 0; g_snd_cmd.param1 = 0;
g_snd_cmd.param2 = 0; g_snd_cmd.param2 = 0;
err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE); err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE);
} else { } else {
g_macsnd_playing = 0; g_macsnd_playing = 0;
} }
} }
int int mac_send_audio(byte *ptr, int in_size) {
mac_send_audio(byte *ptr, int in_size) SndCommand snd_cmd = {0};
{ word32 *wptr, *macptr;
SndCommand snd_cmd = {0}; word32 *eptr;
word32 *wptr, *macptr; int samps;
word32 *eptr; int i;
int samps;
int i;
samps = in_size / 4; samps = in_size / 4;
wptr = (word32 *)ptr; wptr = (word32 *)ptr;
macptr = (word32 *)g_macsnd_rebuf_ptr; macptr = (word32 *)g_macsnd_rebuf_ptr;
eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE]; eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE];
for(i = 0; i < samps; i++) { for(i = 0; i < samps; i++) {
*macptr++ = *wptr++; *macptr++ = *wptr++;
if(macptr >= eptr) { if(macptr >= eptr) {
macptr = &g_macsnd_rebuf[0]; macptr = &g_macsnd_rebuf[0];
} }
} }
g_macsnd_rebuf_ptr = macptr; g_macsnd_rebuf_ptr = macptr;
if(!g_macsnd_playing) { if(!g_macsnd_playing) {
mac_snd_callback(g_snd_channel_ptr, &snd_cmd); mac_snd_callback(g_snd_channel_ptr, &snd_cmd);
} }
return in_size; return in_size;
} }
void void child_sound_init_mac() {
child_sound_init_mac() OSStatus err;
{
OSStatus err;
mac_printf("In mac child\n"); mac_printf("In mac child\n");
fflush(stdout); fflush(stdout);
mac_printf("pid: %d\n", getpid()); mac_printf("pid: %d\n", getpid());
fflush(stdout); fflush(stdout);
//return; //return;
//g_snd_channel_ptr = 0; //g_snd_channel_ptr = 0;
err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo, err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo,
NewSndCallBackUPP(mac_snd_callback)); NewSndCallBackUPP(mac_snd_callback));
mac_printf("SndNewChannel ret: %d\n", (int)err); mac_printf("SndNewChannel ret: %d\n", (int)err);
fflush(stdout); fflush(stdout);
memset(&g_snd_hdr, 0, sizeof(g_snd_hdr)); memset(&g_snd_hdr, 0, sizeof(g_snd_hdr));
g_snd_hdr.sampleSize = 16; g_snd_hdr.sampleSize = 16;
g_snd_hdr.numChannels = 2; g_snd_hdr.numChannels = 2;
g_audio_rate = 44100; g_audio_rate = 44100;
g_snd_hdr.sampleRate = g_audio_rate << 16; g_snd_hdr.sampleRate = g_audio_rate << 16;
g_snd_hdr.numFrames = 0; // will be set in mac_send_audio g_snd_hdr.numFrames = 0; // will be set in mac_send_audio
g_snd_hdr.encode = extSH; g_snd_hdr.encode = extSH;
g_snd_hdr.baseFrequency = 0; g_snd_hdr.baseFrequency = 0;
g_snd_hdr.samplePtr = 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"); mac_printf("End of child_sound_init_mac\n");
fflush(stdout); fflush(stdout);
} }
void void macsnd_init(word32 *shmaddr) {
macsnd_init(word32 *shmaddr) g_macsnd_rebuf_cur = &g_macsnd_rebuf[0];
{ g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0];
g_macsnd_rebuf_cur = &g_macsnd_rebuf[0]; mac_printf("macsnd_init called\n");
g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0]; child_sound_loop(-1, -1, shmaddr);
mac_printf("macsnd_init called\n");
child_sound_loop(-1, -1, shmaddr);
} }
#endif #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 <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -11,9 +17,9 @@
// Halts on bad reads. Sets flags via engine_s.s:set_halt_act() function // 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 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 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 extern int g_ignore_halts; // defined in sim65816.c
// Size of RAM memory expansion card in bytes (default = 8*1024*1024 = 8MB) // Size of RAM memory expansion card in bytes (default = 8*1024*1024 = 8MB)
extern int g_mem_size_exp; // defined in sim65816.c 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 extern int g_dbg_enable_port; // defined in debug.c
// Set preferred audio frequency // Set preferred audio frequency
extern int g_preferred_rate; // defined in sound_driver.c, implemented in various driver files 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 extern int g_audio_enable; // defined in sound.c
// Start in fullscreen mode // Start in fullscreen mode
extern int g_fullscreen; // defined in adb.c, because weird driver writing for x 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); printf ( "TMP %d\n", tmp);
return tmp; return tmp;
} }
int parse_cli_options(int argc, char **argv) { int parse_cli_options(int argc, char **argv) {
int i; int i;
int tmp1; int tmp1;
int skip_amt; 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 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); glogf("%s Setting joystick X axis %d", parse_log_prefix, tmp1);
g_joystick_x_axis = tmp1; g_joystick_x_axis = tmp1;
i++; i++;
} else if(!strcmp("-joy_y", argv[i])) { } else if(!strcmp("-joy_y", argv[i])) {
if((i+1) >= argc) { if((i+1) >= argc) {
glogf("%s Error, option '-joy_y' missing argument", parse_log_prefix); 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 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); glogf("%s Setting joystick X2 axis %d", parse_log_prefix, tmp1);
g_joystick_x2_axis = tmp1; g_joystick_x2_axis = tmp1;
i++; i++;
} else if(!strcmp("-joy_y2", argv[i])) { } else if(!strcmp("-joy_y2", argv[i])) {
if((i+1) >= argc) { if((i+1) >= argc) {
glogf("%s Error, option '-joy_y2' missing argument", parse_log_prefix); glogf("%s Error, option '-joy_y2' missing argument", parse_log_prefix);

View File

@ -1,189 +1,175 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #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; extern int g_mouse_raw_y;
double g_paddle_trig_dcycs = 0.0; double g_paddle_trig_dcycs = 0.0;
int g_swap_paddles = 0; int g_swap_paddles = 0;
int g_invert_paddles = 0; int g_invert_paddles = 0;
int g_joystick_scale_factor_x = 0x100; int g_joystick_scale_factor_x = 0x100;
int g_joystick_scale_factor_y = 0x100; int g_joystick_scale_factor_y = 0x100;
int g_joystick_trim_amount_x = 0; int g_joystick_trim_amount_x = 0;
int g_joystick_trim_amount_y = 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_type = JOYSTICK_TYPE_NATIVE_1; // OG Trying to set native joystick as default
int g_joystick_native_type1 = -1; int g_joystick_native_type1 = -1;
int g_joystick_native_type2 = -1; int g_joystick_native_type2 = -1;
int g_joystick_native_type = -1; int g_joystick_native_type = -1;
extern int g_paddle_buttons; extern int g_paddle_buttons;
int g_paddle_val[4] = { 0, 0, 0, 0 }; int g_paddle_val[4] = { 0, 0, 0, 0 };
/* g_paddle_val[0]: Joystick X coord, [1]:Y coord */ /* g_paddle_val[0]: Joystick X coord, [1]:Y coord */
double g_paddle_dcycs[4] = { 0.0, 0.0, 0.0, 0.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 */ /* g_paddle_dcycs are the dcycs the paddle goes to 0 */
void void paddle_fixup_joystick_type() {
paddle_fixup_joystick_type() /* If g_joystick_type points to an illegal value, change it */
{ if(g_joystick_type == JOYSTICK_TYPE_NATIVE_1) {
/* If g_joystick_type points to an illegal value, change it */ g_joystick_native_type = g_joystick_native_type1;
if(g_joystick_type == JOYSTICK_TYPE_NATIVE_1) { if(g_joystick_native_type1 < 0) {
g_joystick_native_type = g_joystick_native_type1; g_joystick_type = JOYSTICK_TYPE_KEYPAD;
if(g_joystick_native_type1 < 0) { printf("no joy 1 --- switching to keypad\n");
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_type == JOYSTICK_TYPE_NATIVE_2) { if(g_joystick_native_type2 < 0) {
g_joystick_native_type = g_joystick_native_type2; g_joystick_type = JOYSTICK_TYPE_KEYPAD;
if(g_joystick_native_type2 < 0) { printf("no joy 2 --- switching to keypad\n");
g_joystick_type = JOYSTICK_TYPE_KEYPAD; }
printf("no joy 2 --- switching to keypad\n"); }
}
}
} }
void void paddle_trigger(double dcycs) {
paddle_trigger(double dcycs) /* Called by read/write to $c070 */
{ g_paddle_trig_dcycs = dcycs;
/* Called by read/write to $c070 */
g_paddle_trig_dcycs = dcycs;
/* Determine what all the paddle values are right now */ /* Determine what all the paddle values are right now */
paddle_fixup_joystick_type(); paddle_fixup_joystick_type();
switch(g_joystick_type) { switch(g_joystick_type) {
case JOYSTICK_TYPE_KEYPAD: /* Keypad Joystick */ case JOYSTICK_TYPE_KEYPAD: /* Keypad Joystick */
paddle_trigger_keypad(dcycs); paddle_trigger_keypad(dcycs);
break; break;
case JOYSTICK_TYPE_MOUSE: /* Mouse Joystick */ case JOYSTICK_TYPE_MOUSE: /* Mouse Joystick */
paddle_trigger_mouse(dcycs); paddle_trigger_mouse(dcycs);
break; break;
case JOYSTICK_TYPE_NONE: /* Mouse Joystick */ case JOYSTICK_TYPE_NONE: /* Mouse Joystick */
paddle_trigger_mouse(dcycs); paddle_trigger_mouse(dcycs);
break; break;
default: default:
joystick_update(dcycs); joystick_update(dcycs);
} }
} }
void void paddle_trigger_mouse(double dcycs) {
paddle_trigger_mouse(double dcycs) int val_x, val_y;
{ int mouse_x, mouse_y;
int val_x, val_y;
int mouse_x, mouse_y;
val_x = 0; val_x = 0;
mouse_x = g_mouse_raw_x; mouse_x = g_mouse_raw_x;
mouse_y = g_mouse_raw_y; mouse_y = g_mouse_raw_y;
/* mous_phys_x is 0->560, convert that to -32768 to + 32767 cyc */ /* mous_phys_x is 0->560, convert that to -32768 to + 32767 cyc */
/* So subtract 280 then mult by 117 */ /* So subtract 280 then mult by 117 */
val_x = (mouse_x - 280) * 117; val_x = (mouse_x - 280) * 117;
/* mous_phys_y is 0->384, convert that to -32768 to + 32767 cyc */ /* 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 */ /* so subtract 192 then mult by 180 to overscale it a bit */
val_y = (mouse_y - 192) * 180; val_y = (mouse_y - 192) * 180;
g_paddle_val[0] = val_x; g_paddle_val[0] = val_x;
g_paddle_val[1] = val_y; g_paddle_val[1] = val_y;
g_paddle_val[2] = 32767; g_paddle_val[2] = 32767;
g_paddle_val[3] = 32767; g_paddle_val[3] = 32767;
g_paddle_buttons |= 0xc; g_paddle_buttons |= 0xc;
paddle_update_trigger_dcycs(dcycs); paddle_update_trigger_dcycs(dcycs);
} }
void void paddle_trigger_keypad(double dcycs) {
paddle_trigger_keypad(double dcycs) int get_y;
{ int val_x, val_y;
int get_y;
int val_x, val_y;
val_x = adb_get_keypad_xy(get_y=0); val_x = adb_get_keypad_xy(get_y=0);
val_y = adb_get_keypad_xy(get_y=1); val_y = adb_get_keypad_xy(get_y=1);
/* val_x and val_y are already scale -32768 to +32768 */ /* val_x and val_y are already scale -32768 to +32768 */
g_paddle_val[0] = val_x; g_paddle_val[0] = val_x;
g_paddle_val[1] = val_y; g_paddle_val[1] = val_y;
g_paddle_val[2] = 32767; g_paddle_val[2] = 32767;
g_paddle_val[3] = 32767; g_paddle_val[3] = 32767;
g_paddle_buttons |= 0xc; g_paddle_buttons |= 0xc;
paddle_update_trigger_dcycs(dcycs); paddle_update_trigger_dcycs(dcycs);
} }
void void paddle_update_trigger_dcycs(double dcycs) {
paddle_update_trigger_dcycs(double dcycs) double trig_dcycs;
{ int val;
double trig_dcycs; int paddle_num;
int val; int scale, trim;
int paddle_num; int i;
int scale, trim;
int i;
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
paddle_num = i; paddle_num = i;
if(g_swap_paddles) { if(g_swap_paddles) {
paddle_num = i ^ 1; paddle_num = i ^ 1;
} }
val = g_paddle_val[paddle_num]; val = g_paddle_val[paddle_num];
if(g_invert_paddles) { if(g_invert_paddles) {
val = -val; val = -val;
} }
/* convert -32768 to +32768 into 0->2816.0 cycles (the */ /* convert -32768 to +32768 into 0->2816.0 cycles (the */
/* paddle delay const) */ /* paddle delay const) */
/* First multiply by the scale factor to adjust range */ /* First multiply by the scale factor to adjust range */
if(paddle_num & 1) { if(paddle_num & 1) {
scale = g_joystick_scale_factor_y; scale = g_joystick_scale_factor_y;
trim = g_joystick_trim_amount_y; trim = g_joystick_trim_amount_y;
} else { } else {
scale = g_joystick_scale_factor_x; scale = g_joystick_scale_factor_x;
trim = g_joystick_trim_amount_x; trim = g_joystick_trim_amount_x;
} }
#if 0 #if 0
if(i == 0) { if(i == 0) {
printf("val was %04x(%d) * scale %03x = %d\n", printf("val was %04x(%d) * scale %03x = %d\n",
val, val, scale, (val*scale)>>16); val, val, scale, (val*scale)>>16);
} }
#endif #endif
val = val * scale >> 16; val = val * scale >> 16;
/* Val is now from -128 to + 128 since scale is */ /* Val is now from -128 to + 128 since scale is */
/* 256=1.0, 128 = 0.5 */ /* 256=1.0, 128 = 0.5 */
val = val + 128 + trim; val = val + 128 + trim;
if(val >= 255) { if(val >= 255) {
val = 280; /* increase range */ val = 280; /* increase range */
} }
trig_dcycs = dcycs + (val * 11.04); trig_dcycs = dcycs + (val * 11.04);
g_paddle_dcycs[i] = trig_dcycs; g_paddle_dcycs[i] = trig_dcycs;
} }
} }
int int read_paddles(double dcycs, int paddle) {
read_paddles(double dcycs, int paddle) double trig_dcycs;
{
double trig_dcycs;
trig_dcycs = g_paddle_dcycs[paddle & 3]; trig_dcycs = g_paddle_dcycs[paddle & 3];
if(dcycs < trig_dcycs) { if(dcycs < trig_dcycs) {
return 0x80; return 0x80;
} else { } else {
return 0x00; return 0x00;
} }
} }
void void paddle_update_buttons() {
paddle_update_buttons() paddle_fixup_joystick_type();
{ joystick_update_buttons();
paddle_fixup_joystick_type();
joystick_update_buttons();
} }

View File

@ -1,17 +1,15 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) 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
This file handles the Apple II Parallel Card emulation in slot 1. Its very parallel port, files, and additional types of emulated printers.
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 "defc.h"
#include "printer.h" #include "printer.h"
@ -21,42 +19,40 @@ extern int g_printer_timeout;
word32 printer_vbl_count = 0; word32 printer_vbl_count = 0;
int port_block = 0; int port_block = 0;
byte parallel_read(word16 io_address) byte parallel_read(word16 io_address) {
{ //printf("parallel card status called at %x\n", io_address);
//printf("parallel card status called at %x\n", io_address); //since we only have a virtual printer, always return state as "Ready"
//since we only have a virtual printer, always return state as "Ready" return 0xff;
return 0xff;
} }
void parallel_write(word16 io_address, byte val)
{ void parallel_write(word16 io_address, byte val) {
//Mask MSB if user has it set. //Mask MSB if user has it set.
if(g_parallel_out_masking) { if(g_parallel_out_masking) {
val = val & 0x7f; val = val & 0x7f;
} }
//printf("parallel card called at %x\n", io_address); //printf("parallel card called at %x\n", io_address);
//send a byte to the virtual printer //send a byte to the virtual printer
//By default all output to $C090 gets sent to the printer //By default all output to $C090 gets sent to the printer
if (io_address == 0x00) if (io_address == 0x00)
{ {
port_block = 1; port_block = 1;
printer_loop(val); printer_loop(val);
printer_vbl_count = g_vbl_count+(g_printer_timeout*60); printer_vbl_count = g_vbl_count+(g_printer_timeout*60);
port_block = 0; port_block = 0;
} }
return; return;
} }
//This function handles the automatic timeout of the virtual printer if an //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 //application doesn't send a form feed at the end of the page. It also
//allows multipage mode Postscript and native printer documents to //allows multipage mode Postscript and native printer documents to
//print somewhat how a regular application would. //print somewhat how a regular application would.
void printer_update() void printer_update() {
{ if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count)
if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count) {
{ printf("Calling printer_update and flushing!\n");
printf("Calling printer_update and flushing!\n"); printer_feed();
printer_feed(); printer_vbl_count = 0;
printer_vbl_count = 0; }
} return;
return;
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #include "defc.h"
#include <fcntl.h> #include <fcntl.h>
@ -11,131 +11,127 @@
#include <errno.h> #include <errno.h>
#define BUF_SIZE 65536 #define BUF_SIZE 65536
char buf[BUF_SIZE]; char buf[BUF_SIZE];
void void read_block(int fd, char *buf, int blk, int blk_size) {
read_block(int fd, char *buf, int blk, int blk_size) int ret;
{
int ret;
ret = lseek(fd, blk * blk_size, SEEK_SET); ret = lseek(fd, blk * blk_size, SEEK_SET);
if(ret != blk * blk_size) { if(ret != blk * blk_size) {
printf("lseek: %d, errno: %d\n", ret, errno); printf("lseek: %d, errno: %d\n", ret, errno);
exit(1); exit(1);
} }
ret = read(fd, buf, blk_size); ret = read(fd, buf, blk_size);
if(ret != blk_size) { if(ret != blk_size) {
printf("ret: %d, errno: %d\n", ret, errno); printf("ret: %d, errno: %d\n", ret, errno);
exit(1); exit(1);
} }
} }
int int main(int argc, char **argv) {
main(int argc, char **argv) Driver_desc *driver_desc_ptr;
{ Part_map *part_map_ptr;
Driver_desc *driver_desc_ptr; double dsize;
Part_map *part_map_ptr; int fd;
double dsize; int block_size;
int fd; word32 sig;
int block_size; word32 map_blk_cnt;
word32 sig; word32 phys_part_start;
word32 map_blk_cnt; word32 part_blk_cnt;
word32 phys_part_start; word32 data_start;
word32 part_blk_cnt; word32 data_cnt;
word32 data_start; int map_blocks;
word32 data_cnt; int cur;
int map_blocks; int long_form;
int cur; int last_arg;
int long_form; int i;
int last_arg;
int i;
/* parse args */ /* parse args */
long_form = 0; long_form = 0;
last_arg = 1; last_arg = 1;
for(i = 1; i < argc; i++) { for(i = 1; i < argc; i++) {
if(!strcmp("-l", argv[i])) { if(!strcmp("-l", argv[i])) {
long_form = 1; long_form = 1;
} else { } else {
last_arg = i; last_arg = i;
break; break;
} }
} }
fd = open(argv[last_arg], O_RDONLY | O_BINARY, 0x1b6); fd = open(argv[last_arg], O_RDONLY | O_BINARY, 0x1b6);
if(fd < 0) { if(fd < 0) {
printf("open %s, ret: %d, errno:%d\n", argv[last_arg],fd,errno); printf("open %s, ret: %d, errno:%d\n", argv[last_arg],fd,errno);
exit(1); exit(1);
} }
if(long_form) { if(long_form) {
printf("fd: %d\n", fd); printf("fd: %d\n", fd);
} }
block_size = 512; block_size = 512;
read_block(fd, buf, 0, block_size); read_block(fd, buf, 0, block_size);
driver_desc_ptr = (Driver_desc *)buf; driver_desc_ptr = (Driver_desc *)buf;
sig = GET_BE_WORD16(driver_desc_ptr->sig); sig = GET_BE_WORD16(driver_desc_ptr->sig);
block_size = GET_BE_WORD16(driver_desc_ptr->blk_size); block_size = GET_BE_WORD16(driver_desc_ptr->blk_size);
if(long_form) { if(long_form) {
printf("sig: %04x, blksize: %04x\n", sig, block_size); printf("sig: %04x, blksize: %04x\n", sig, block_size);
} }
if(block_size == 0) { if(block_size == 0) {
block_size = 512; block_size = 512;
} }
if(sig == 0x4552 && block_size >= 0x200) { if(sig == 0x4552 && block_size >= 0x200) {
if(long_form) { if(long_form) {
printf("good!\n"); printf("good!\n");
} }
} else { } else {
printf("bad sig:%04x or block_size:%04x!\n", sig, block_size); printf("bad sig:%04x or block_size:%04x!\n", sig, block_size);
exit(1); exit(1);
} }
map_blocks = 1; map_blocks = 1;
cur = 0; cur = 0;
while(cur < map_blocks) { while(cur < map_blocks) {
read_block(fd, buf, cur + 1, block_size); read_block(fd, buf, cur + 1, block_size);
part_map_ptr = (Part_map *)buf; part_map_ptr = (Part_map *)buf;
sig = GET_BE_WORD16(part_map_ptr->sig); sig = GET_BE_WORD16(part_map_ptr->sig);
map_blk_cnt = GET_BE_WORD32(part_map_ptr->map_blk_cnt); map_blk_cnt = GET_BE_WORD32(part_map_ptr->map_blk_cnt);
phys_part_start = GET_BE_WORD32(part_map_ptr->phys_part_start); phys_part_start = GET_BE_WORD32(part_map_ptr->phys_part_start);
part_blk_cnt = GET_BE_WORD32(part_map_ptr->part_blk_cnt); part_blk_cnt = GET_BE_WORD32(part_map_ptr->part_blk_cnt);
data_start = GET_BE_WORD32(part_map_ptr->data_start); data_start = GET_BE_WORD32(part_map_ptr->data_start);
data_cnt = GET_BE_WORD32(part_map_ptr->data_cnt); data_cnt = GET_BE_WORD32(part_map_ptr->data_cnt);
if(cur == 0) { if(cur == 0) {
map_blocks = MIN(100, map_blk_cnt); map_blocks = MIN(100, map_blk_cnt);
} }
if(long_form) { if(long_form) {
printf("%2d: sig: %04x, map_blk_cnt: %d, " printf("%2d: sig: %04x, map_blk_cnt: %d, "
"phys_part_start: %08x, part_blk_cnt: %08x\n", "phys_part_start: %08x, part_blk_cnt: %08x\n",
cur, sig, map_blk_cnt, phys_part_start, cur, sig, map_blk_cnt, phys_part_start,
part_blk_cnt); part_blk_cnt);
printf(" part_name: %s, part_type: %s\n", printf(" part_name: %s, part_type: %s\n",
part_map_ptr->part_name, part_map_ptr->part_name,
part_map_ptr->part_type); part_map_ptr->part_type);
printf(" data_start:%08x, data_cnt:%08x status:%08x\n", 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_start),
GET_BE_WORD32(part_map_ptr->data_cnt), GET_BE_WORD32(part_map_ptr->data_cnt),
GET_BE_WORD32(part_map_ptr->part_status)); GET_BE_WORD32(part_map_ptr->part_status));
printf(" processor: %s\n", part_map_ptr->processor); printf(" processor: %s\n", part_map_ptr->processor);
} else { } else {
dsize = (double)GET_BE_WORD32(part_map_ptr->data_cnt); dsize = (double)GET_BE_WORD32(part_map_ptr->data_cnt);
printf("%2d:%-20s size=%6.2fMB type=%s\n", cur, printf("%2d:%-20s size=%6.2fMB type=%s\n", cur,
part_map_ptr->part_name, part_map_ptr->part_name,
(dsize/(1024.0*2.0)), (dsize/(1024.0*2.0)),
part_map_ptr->part_type); part_map_ptr->part_type);
} }
cur++; cur++;
} }
close(fd); close(fd);
return 0; return 0;
} }

View File

@ -1,23 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Copyright (C) 2010 - 2011 by GSport contributors Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey See LICENSE.txt for license (GPL v2)
*/
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
*/
/* /*
* Copyright (C) 2002-2004 The DOSBox Team * 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/* This is an interface between the SCC emulation and the Virtual Imagewriter. */ /* 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 imagewriter_port_block = 0;
int iw_scc_write = 0; int iw_scc_write = 0;
int scc_imagewriter_init(int port) int scc_imagewriter_init(int port) {
{ Scc *scc_ptr;
Scc *scc_ptr; scc_ptr = &(scc_stat[port]);
scc_ptr = &(scc_stat[port]); imagewriter_init(g_imagewriter_dpi,g_imagewriter_paper,g_imagewriter_banner,g_imagewriter_output,g_imagewriter_multipage);
imagewriter_init(g_imagewriter_dpi,g_imagewriter_paper,g_imagewriter_banner,g_imagewriter_output,g_imagewriter_multipage); scc_ptr->state = 4;
scc_ptr->state = 4; return 4;
return 4;
} }
/** Transfer data from Imagewriter to the SCC **/ /** Transfer data from Imagewriter to the SCC **/
void scc_imagewriter_fill_readbuf(int port, int space_left, double dcycs) void scc_imagewriter_fill_readbuf(int port, int space_left, double dcycs) {
{ if (iw_scc_write)
if (iw_scc_write) {
{ size_t bytes_read;
size_t bytes_read; size_t i;
size_t i; byte data[9];
byte data[9]; if (g_imagewriter == 1)
if (g_imagewriter == 1) {
{ //Imagewriter LQ self ID string. Tell machine we have a color ribbon and sheet feeder installed.
//Imagewriter LQ self ID string. Tell machine we have a color ribbon and sheet feeder installed. data[0] = 0; //Start bit
data[0] = 0; //Start bit data[1] ='L'; //Printer type is Imagewriter LQ
data[1] ='L'; //Printer type is Imagewriter LQ data[2] ='Q'; //(cont)
data[2] ='Q'; //(cont) data[3] ='1'; //15 inch carriage width
data[3] ='1'; //15 inch carriage width data[4] ='C'; //Color ribbon installed
data[4] ='C'; //Color ribbon installed data[5] ='F'; //Sheet feeder installed, no envelope attachment
data[5] ='F'; //Sheet feeder installed, no envelope attachment data[6] ='1'; //Number of sheet feeder bins
data[6] ='1'; //Number of sheet feeder bins data[7] = 0x0D; //CR terminates string
data[7] = 0x0D; //CR terminates string data[8] = 0; //Stop bit
data[8] = 0; //Stop bit bytes_read = 9;
bytes_read = 9; }
} else
else {
{ //Imagewriter II self ID string. Tell machine we have a color ribbon and sheet feeder installed.
//Imagewriter II self ID string. Tell machine we have a color ribbon and sheet feeder installed. data[0] = 0; //Start bit
data[0] = 0; //Start bit data[1] ='I'; //Printer type is Imagewriter II
data[1] ='I'; //Printer type is Imagewriter II data[2] ='W'; //(cont)
data[2] ='W'; //(cont) data[3] ='1'; //10 inch carriage width
data[3] ='1'; //10 inch carriage width data[4] ='0'; //(cont)
data[4] ='0'; //(cont) data[5] ='C'; //Color ribbon installed
data[5] ='C'; //Color ribbon installed data[6] ='F'; //Sheet feeder installed
data[6] ='F'; //Sheet feeder installed data[7] = 0; //Stop bit
data[7] = 0; //Stop bit bytes_read = 8;
bytes_read = 8; }
} for(i = 0; i < bytes_read; i++) {
for(i = 0; i < bytes_read; i++) { scc_add_to_readbuf(port, data[i], dcycs);
scc_add_to_readbuf(port, data[i], dcycs); }
} iw_scc_write = 0;
iw_scc_write = 0; }
}
} }
/** Transfer data from the SCC to the Imagewriter. **/ /** Transfer data from the SCC to the Imagewriter. **/
void scc_imagewriter_empty_writebuf(int port, double dcycs) void scc_imagewriter_empty_writebuf(int port, double dcycs) {
{ Scc* scc_ptr;
Scc* scc_ptr;
int rdptr; int rdptr;
int wrptr; int wrptr;
int len; int len;
int done; int done;
//int ret; //int ret;
unsigned long bytes_written; unsigned long bytes_written;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
done = 0; done = 0;
while(!done) { while(!done) {
rdptr = scc_ptr->out_rdptr; rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr; wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr) { if(rdptr == wrptr) {
//printf("...rdptr == wrptr\n"); //printf("...rdptr == wrptr\n");
done = 1; done = 1;
break; break;
} }
len = wrptr - rdptr; len = wrptr - rdptr;
if(len < 0) { if(len < 0) {
len = SCC_OUTBUF_SIZE - rdptr; len = SCC_OUTBUF_SIZE - rdptr;
} }
if(len > 32) { if(len > 32) {
len = 32; len = 32;
} }
if(len <= 0) { if(len <= 0) {
done = 1; done = 1;
break; break;
} }
bytes_written = 1; bytes_written = 1;
imagewriter_port_block = 1; imagewriter_port_block = 1;
imagewriter_loop(scc_ptr->out_buf[rdptr]); imagewriter_loop(scc_ptr->out_buf[rdptr]);
imagewriter_vbl_count = g_vbl_count+(g_imagewriter_timeout*60); imagewriter_vbl_count = g_vbl_count+(g_imagewriter_timeout*60);
imagewriter_port_block = 0; imagewriter_port_block = 0;
//printf("Write Imagewriter ret: %d, bytes_written:%d, len:%d\n", ret, //printf("Write Imagewriter ret: %d, bytes_written:%d, len:%d\n", ret,
//(int)bytes_written, len); //(int)bytes_written, len);
if (bytes_written == 0) { if (bytes_written == 0) {
done = 1; done = 1;
break; break;
} else { } else {
rdptr = rdptr + bytes_written; rdptr = rdptr + bytes_written;
if(rdptr >= SCC_OUTBUF_SIZE) { if(rdptr >= SCC_OUTBUF_SIZE) {
rdptr = rdptr - SCC_OUTBUF_SIZE; rdptr = rdptr - SCC_OUTBUF_SIZE;
} }
scc_ptr->out_rdptr = rdptr; scc_ptr->out_rdptr = rdptr;
} }
} }
} }
//This function handles the automatic timeout of the virtual printer if an //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 //application doesn't send a form feed at the end of the page. It also
//allows multipage mode Postscript and native printer documents to //allows multipage mode Postscript and native printer documents to
//print somewhat how a regular application would. //print somewhat how a regular application would.
void imagewriter_update() void imagewriter_update() {
{ if (imagewriter_port_block != 1 && imagewriter_vbl_count != 0 && g_vbl_count >= imagewriter_vbl_count)
if (imagewriter_port_block != 1 && imagewriter_vbl_count != 0 && g_vbl_count >= imagewriter_vbl_count) {
{ printf("Calling imagewriter_update and flushing!\n");
printf("Calling imagewriter_update and flushing!\n"); imagewriter_feed();
imagewriter_feed(); imagewriter_vbl_count = 0;
imagewriter_vbl_count = 0; }
} return;
return;
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/* This is an interface between the SCC emulation and the LAP bridge. */ /* 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; extern int g_config_gsplus_update_needed;
static bool bridge_initialized = false; static bool bridge_initialized = false;
void scc_llap_init() void scc_llap_init() {
{ atbridge_set_diagnostics(g_appletalk_diagnostics);
atbridge_set_diagnostics(g_appletalk_diagnostics); bridge_initialized = atbridge_init();
bridge_initialized = atbridge_init(); atbridge_set_net(g_appletalk_network_hint);
atbridge_set_net(g_appletalk_network_hint);
} }
void scc_llap_set_node(byte val) void scc_llap_set_node(byte val) {
{ atbridge_set_node(val);
atbridge_set_node(val);
} }
void scc_llap_update() void scc_llap_update() {
{ if (bridge_initialized)
if (bridge_initialized) {
{ atbridge_process();
atbridge_process();
// Save the AppleTalk network number. Since the network number does not // Save the AppleTalk network number. Since the network number does not
// change very often, this will slightly improve startup time. // change very often, this will slightly improve startup time.
if (g_appletalk_network_hint != atbridge_get_net()) if (g_appletalk_network_hint != atbridge_get_net())
{ {
g_appletalk_network_hint = atbridge_get_net(); g_appletalk_network_hint = atbridge_get_net();
g_config_gsplus_update_needed = 1; g_config_gsplus_update_needed = 1;
} }
} }
} }
/** Transfer one packet from the bridge to the SCC **/ /** Transfer one packet from the bridge to the SCC **/
void scc_llap_fill_readbuf(int port, int space_left, double dcycs) void scc_llap_fill_readbuf(int port, int space_left, double dcycs) {
{ atbridge_set_diagnostics(g_appletalk_diagnostics);
atbridge_set_diagnostics(g_appletalk_diagnostics);
byte* data; byte* data;
if (!bridge_initialized) if (!bridge_initialized)
return; return;
data = NULL; data = NULL;
size_t bytes_read; size_t bytes_read;
size_t i; size_t i;
llap_dequeue_out(dcycs, &bytes_read, &data); llap_dequeue_out(dcycs, &bytes_read, &data);
for(i = 0; i < bytes_read; i++) { for(i = 0; i < bytes_read; i++) {
scc_add_to_readbuf(port, data[i], dcycs); 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. // Normally, the bridge updates from the 60 Hz loop, but that alone bottlenecks network throughput.
scc_llap_update(); scc_llap_update();
} }
/** Transfer one packet from the SCC to the AppleTalk bridge. **/ /** Transfer one packet from the SCC to the AppleTalk bridge. **/
void scc_llap_empty_writebuf(int port, double dcycs) void scc_llap_empty_writebuf(int port, double dcycs) {
{ atbridge_set_diagnostics(g_appletalk_diagnostics);
atbridge_set_diagnostics(g_appletalk_diagnostics);
Scc* scc_ptr; Scc* scc_ptr;
if (!bridge_initialized) if (!bridge_initialized)
return; return;
int rdptr; int rdptr;
int wrptr; int wrptr;
int len; int len;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
// If there's data in the output buffer, send it. // If there's data in the output buffer, send it.
rdptr = scc_ptr->out_rdptr; rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr; wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr) if(rdptr == wrptr)
return; 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;
// Latch EOM to indicate that the SCC has sent the message. len = wrptr - rdptr;
// The timing will be a bit off from the real hardware since we're not if (len < 0)
// emulating the sending hardware timing and CRC generation. {
scc_ptr->eom = 1; // 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. // Remove the sent data from the output buffer. Since the buffer contains
scc_llap_update(); // 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 #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 #endif

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/* This file contains the Mac serial calls */ /* This file contains the Mac serial calls */
@ -18,191 +18,183 @@ extern Scc scc_stat[2];
extern word32 g_c025_val; extern word32 g_c025_val;
#ifdef MAC #ifdef MAC
int int scc_serial_mac_init(int port) {
scc_serial_mac_init(int port) char str_buf[1024];
{ Scc *scc_ptr;
char str_buf[1024]; int state;
Scc *scc_ptr; int fd;
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.USA19QW11P1.1"); */
sprintf(&str_buf[0], "/dev/tty.USA19H181P1.1"); sprintf(&str_buf[0], "/dev/tty.USA19H181P1.1");
/* HACK: fix this... */ /* 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_handle = (void *)fd;
scc_ptr->host_handle2 = 0; 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) { if(fd < 0) {
scc_ptr->host_handle = (void *)-1; scc_ptr->host_handle = (void *)-1;
return -1; return -1;
} }
scc_serial_mac_change_params(port); scc_serial_mac_change_params(port);
state = 2; /* raw serial */ state = 2; /* raw serial */
scc_ptr->state = state; scc_ptr->state = state;
return state; return state;
} }
void void scc_serial_mac_change_params(int port) {
scc_serial_mac_change_params(int port) struct termios termios_buf;
{ Scc *scc_ptr;
struct termios termios_buf; int fd;
Scc *scc_ptr; int csz;
int fd; int ret;
int csz;
int ret;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
fd = (intptr_t)scc_ptr->host_handle; fd = (intptr_t)scc_ptr->host_handle;
printf("scc_serial_mac_change_parms port: %d, fd: %d\n", port, fd); printf("scc_serial_mac_change_parms port: %d, fd: %d\n", port, fd);
if(fd <= 0) { if(fd <= 0) {
return; return;
} }
ret = tcgetattr(fd, &termios_buf); ret = tcgetattr(fd, &termios_buf);
if(ret != 0) { if(ret != 0) {
printf("tcgetattr port%d ret: %d\n", port, ret); printf("tcgetattr port%d ret: %d\n", port, ret);
} }
#if 1 #if 1
printf("baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n", 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_ispeed, (int)termios_buf.c_iflag,
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag, (int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
(int)termios_buf.c_lflag); (int)termios_buf.c_lflag);
#endif #endif
memset(&termios_buf, 0, sizeof(struct termios)); memset(&termios_buf, 0, sizeof(struct termios));
cfmakeraw(&termios_buf); cfmakeraw(&termios_buf);
cfsetspeed(&termios_buf, scc_ptr->baud_rate); cfsetspeed(&termios_buf, scc_ptr->baud_rate);
csz = scc_ptr->char_size; csz = scc_ptr->char_size;
termios_buf.c_cflag = CREAD | CLOCAL; termios_buf.c_cflag = CREAD | CLOCAL;
termios_buf.c_cflag |= (csz == 5) ? CS5 : termios_buf.c_cflag |= (csz == 5) ? CS5 :
(csz == 6) ? CS6 : (csz == 6) ? CS6 :
(csz == 7) ? CS7 : (csz == 7) ? CS7 :
CS8; CS8;
switch((scc_ptr->reg[4] >> 2) & 0x3) { switch((scc_ptr->reg[4] >> 2) & 0x3) {
case 2: // 1.5 stop bits case 2: // 1.5 stop bits
termios_buf.c_cflag |= CSTOPB; /* no 1.5 stop bit setting.*/ termios_buf.c_cflag |= CSTOPB; /* no 1.5 stop bit setting.*/
break; break;
case 3: // 2 stop bits case 3: // 2 stop bits
termios_buf.c_cflag |= CSTOPB; termios_buf.c_cflag |= CSTOPB;
break; break;
} }
switch((scc_ptr->reg[4]) & 0x3) { switch((scc_ptr->reg[4]) & 0x3) {
case 1: // Odd parity case 1: // Odd parity
termios_buf.c_cflag |= (PARENB | PARODD); termios_buf.c_cflag |= (PARENB | PARODD);
break; break;
case 3: // Even parity case 3: // Even parity
termios_buf.c_cflag |= PARENB; termios_buf.c_cflag |= PARENB;
break; break;
} }
/* always enabled DTR and RTS control */ /* always enabled DTR and RTS control */
termios_buf.c_cflag |= CDTR_IFLOW | CRTS_IFLOW; termios_buf.c_cflag |= CDTR_IFLOW | CRTS_IFLOW;
printf("fd: %d, baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n", 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, 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_oflag, (int)termios_buf.c_cflag,
(int)termios_buf.c_lflag); (int)termios_buf.c_lflag);
ret = tcsetattr(fd, TCSANOW, &termios_buf); ret = tcsetattr(fd, TCSANOW, &termios_buf);
if(ret != 0) { if(ret != 0) {
printf("tcsetattr ret: %d\n", ret); printf("tcsetattr ret: %d\n", ret);
} }
} }
void void scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs) {
scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs) byte tmp_buf[256];
{ Scc *scc_ptr;
byte tmp_buf[256]; int fd;
Scc *scc_ptr; int i;
int fd; int ret;
int i;
int ret;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
fd = (intptr_t)scc_ptr->host_handle; fd = (intptr_t)scc_ptr->host_handle;
if(fd <= 0) { if(fd <= 0) {
return; return;
} }
/* Try reading some bytes */ /* Try reading some bytes */
space_left = MIN(space_left, 256); space_left = MIN(space_left, 256);
ret = read(fd, tmp_buf, space_left); 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 void scc_serial_mac_empty_writebuf(int port) {
scc_serial_mac_empty_writebuf(int port) Scc *scc_ptr;
{ int fd;
Scc *scc_ptr; int rdptr;
int fd; int wrptr;
int rdptr; int done;
int wrptr; int ret;
int done; int len;
int ret;
int len;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
fd = (intptr_t)scc_ptr->host_handle; fd = (intptr_t)scc_ptr->host_handle;
if(fd <= 0) { if(fd <= 0) {
return; return;
} }
/* Try writing some bytes */ /* Try writing some bytes */
done = 0; done = 0;
while(!done) { while(!done) {
rdptr = scc_ptr->out_rdptr; rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr; wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr) { if(rdptr == wrptr) {
//printf("...rdptr == wrptr\n"); //printf("...rdptr == wrptr\n");
done = 1; done = 1;
break; break;
} }
len = wrptr - rdptr; len = wrptr - rdptr;
if(len < 0) { if(len < 0) {
len = SCC_OUTBUF_SIZE - rdptr; len = SCC_OUTBUF_SIZE - rdptr;
} }
if(len > 32) { if(len > 32) {
len = 32; len = 32;
} }
if(len <= 0) { if(len <= 0) {
done = 1; done = 1;
break; break;
} }
ret = write(fd, &(scc_ptr->out_buf[rdptr]), len); ret = write(fd, &(scc_ptr->out_buf[rdptr]), len);
if(ret <= 0) { if(ret <= 0) {
done = 1; done = 1;
break; break;
} else { } else {
rdptr = rdptr + ret; rdptr = rdptr + ret;
if(rdptr >= SCC_OUTBUF_SIZE) { if(rdptr >= SCC_OUTBUF_SIZE) {
rdptr = rdptr - SCC_OUTBUF_SIZE; rdptr = rdptr - SCC_OUTBUF_SIZE;
} }
scc_ptr->out_rdptr = rdptr; 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
/* This file contains the Win32 COM1/COM2 calls */ /* This file contains the Win32 COM1/COM2 calls */
@ -23,238 +23,230 @@ extern Scc scc_stat[2];
extern word32 g_c025_val; extern word32 g_c025_val;
#ifdef _WIN32 #ifdef _WIN32
int int scc_serial_win_init(int port) {
scc_serial_win_init(int port) COMMTIMEOUTS commtimeouts;
{ TCHAR str_buf[8];
COMMTIMEOUTS commtimeouts; Scc *scc_ptr;
TCHAR str_buf[8]; HANDLE host_handle;
Scc *scc_ptr; int state;
HANDLE host_handle; int ret;
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 #ifdef UNICODE
wsprintf(&str_buf[0], _T("COM%d"), port+1); wsprintf(&str_buf[0], _T("COM%d"), port+1);
#else #else
sprintf(&str_buf[0], "COM%d", port+1); sprintf(&str_buf[0], "COM%d", port+1);
#endif #endif
host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE, host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL); 0, NULL, OPEN_EXISTING, 0, NULL);
scc_ptr->host_handle = host_handle; scc_ptr->host_handle = host_handle;
scc_ptr->host_handle2 = malloc(sizeof(DCB)); scc_ptr->host_handle2 = malloc(sizeof(DCB));
printf("scc_socket_init %d called, host_handle: %p\n", port, printf("scc_socket_init %d called, host_handle: %p\n", port,
host_handle); host_handle);
if(host_handle == INVALID_HANDLE_VALUE) { if(host_handle == INVALID_HANDLE_VALUE) {
scc_ptr->host_handle = 0; scc_ptr->host_handle = 0;
return 0; return 0;
} }
scc_serial_win_change_params(port); scc_serial_win_change_params(port);
commtimeouts.ReadIntervalTimeout = MAXDWORD; commtimeouts.ReadIntervalTimeout = MAXDWORD;
commtimeouts.ReadTotalTimeoutMultiplier = 0; commtimeouts.ReadTotalTimeoutMultiplier = 0;
commtimeouts.ReadTotalTimeoutConstant = 0; commtimeouts.ReadTotalTimeoutConstant = 0;
commtimeouts.WriteTotalTimeoutMultiplier = 0; commtimeouts.WriteTotalTimeoutMultiplier = 0;
commtimeouts.WriteTotalTimeoutConstant = 10; commtimeouts.WriteTotalTimeoutConstant = 10;
ret = SetCommTimeouts(host_handle, &commtimeouts); ret = SetCommTimeouts(host_handle, &commtimeouts);
if(ret == 0) { if(ret == 0) {
printf("setcommtimeout ret: %d\n", ret); printf("setcommtimeout ret: %d\n", ret);
} }
state = 2; /* raw serial */ state = 2; /* raw serial */
scc_ptr->state = state; scc_ptr->state = state;
return state; return state;
} }
void void scc_serial_win_change_params(int port) {
scc_serial_win_change_params(int port) DCB *dcbptr;
{ HANDLE host_handle;
DCB *dcbptr; Scc *scc_ptr;
HANDLE host_handle; int ret;
Scc *scc_ptr;
int ret;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
host_handle = scc_ptr->host_handle; host_handle = scc_ptr->host_handle;
dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast
if(host_handle == 0) { if(host_handle == 0) {
return; return;
} }
ret = GetCommState(host_handle, dcbptr); ret = GetCommState(host_handle, dcbptr);
if(ret == 0) { if(ret == 0) {
printf("getcomm port%d ret: %d\n", port, ret); printf("getcomm port%d ret: %d\n", port, ret);
} }
#if 1 #if 1
printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n", printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n",
(int)dcbptr->BaudRate, (int)dcbptr->ByteSize, (int)dcbptr->BaudRate, (int)dcbptr->ByteSize,
(int)dcbptr->StopBits, (int)dcbptr->Parity); (int)dcbptr->StopBits, (int)dcbptr->Parity);
printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n", printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n",
(int)dcbptr->fBinary, (int)dcbptr->fBinary,
(int)dcbptr->fOutxCtsFlow, (int)dcbptr->fOutxCtsFlow,
(int)dcbptr->fOutxDsrFlow, (int)dcbptr->fOutxDsrFlow,
(int)dcbptr->fDtrControl, (int)dcbptr->fDtrControl,
(int)dcbptr->fDsrSensitivity); (int)dcbptr->fDsrSensitivity);
printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n", printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n",
(int)dcbptr->fTXContinueOnXoff, (int)dcbptr->fTXContinueOnXoff,
(int)dcbptr->fOutX, (int)dcbptr->fOutX,
(int)dcbptr->fInX, (int)dcbptr->fInX,
(int)dcbptr->fNull, (int)dcbptr->fNull,
(int)dcbptr->fRtsControl); (int)dcbptr->fRtsControl);
printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError, printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError,
(int)dcbptr->fParity); (int)dcbptr->fParity);
#endif #endif
dcbptr->fAbortOnError = 0; dcbptr->fAbortOnError = 0;
dcbptr->BaudRate = scc_ptr->baud_rate; dcbptr->BaudRate = scc_ptr->baud_rate;
dcbptr->ByteSize = scc_ptr->char_size; dcbptr->ByteSize = scc_ptr->char_size;
dcbptr->StopBits = ONESTOPBIT; dcbptr->StopBits = ONESTOPBIT;
switch((scc_ptr->reg[4] >> 2) & 0x3) { switch((scc_ptr->reg[4] >> 2) & 0x3) {
case 2: // 1.5 stop bits case 2: // 1.5 stop bits
dcbptr->StopBits = ONE5STOPBITS; dcbptr->StopBits = ONE5STOPBITS;
break; break;
case 3: // 2 stop bits case 3: // 2 stop bits
dcbptr->StopBits = TWOSTOPBITS; dcbptr->StopBits = TWOSTOPBITS;
break; break;
} }
dcbptr->Parity = NOPARITY; dcbptr->Parity = NOPARITY;
switch((scc_ptr->reg[4]) & 0x3) { switch((scc_ptr->reg[4]) & 0x3) {
case 1: // Odd parity case 1: // Odd parity
dcbptr->Parity = ODDPARITY; dcbptr->Parity = ODDPARITY;
break; break;
case 3: // Even parity case 3: // Even parity
dcbptr->Parity = EVENPARITY; dcbptr->Parity = EVENPARITY;
break; break;
} }
dcbptr->fNull = 0; dcbptr->fNull = 0;
dcbptr->fDtrControl = DTR_CONTROL_ENABLE; dcbptr->fDtrControl = DTR_CONTROL_ENABLE;
dcbptr->fDsrSensitivity = 0; dcbptr->fDsrSensitivity = 0;
dcbptr->fOutxCtsFlow = 0; dcbptr->fOutxCtsFlow = 0;
dcbptr->fOutxDsrFlow = 0; dcbptr->fOutxDsrFlow = 0;
dcbptr->fParity = 0; dcbptr->fParity = 0;
dcbptr->fInX = 0; dcbptr->fInX = 0;
dcbptr->fOutX = 0; dcbptr->fOutX = 0;
dcbptr->fRtsControl = RTS_CONTROL_ENABLE; dcbptr->fRtsControl = RTS_CONTROL_ENABLE;
ret = SetCommState(host_handle, dcbptr); ret = SetCommState(host_handle, dcbptr);
if(ret == 0) { if(ret == 0) {
printf("SetCommState ret: %d, new baud: %d\n", ret, printf("SetCommState ret: %d, new baud: %d\n", ret,
(int)dcbptr->BaudRate); (int)dcbptr->BaudRate);
} }
} }
void void scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) {
scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) byte tmp_buf[256];
{ Scc *scc_ptr;
byte tmp_buf[256]; HANDLE host_handle;
Scc *scc_ptr; DWORD bytes_read;
HANDLE host_handle; DWORD i;
DWORD bytes_read; int ret;
DWORD i;
int ret;
scc_ptr = &(scc_stat[port]); scc_ptr = &(scc_stat[port]);
host_handle = scc_ptr->host_handle; host_handle = scc_ptr->host_handle;
if(host_handle == 0) { if(host_handle == 0) {
return; return;
} }
/* Try reading some bytes */ /* Try reading some bytes */
space_left = MIN(256, space_left); space_left = MIN(256, space_left);
ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL); ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL);
if(ret == 0) { if(ret == 0) {
printf("ReadFile ret 0\n"); 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 void scc_serial_win_empty_writebuf(int port) {
scc_serial_win_empty_writebuf(int port) Scc *scc_ptr;
{ HANDLE host_handle;
Scc *scc_ptr; int rdptr;
HANDLE host_handle; int wrptr;
int rdptr; int done;
int wrptr; word32 err_code;
int done; DWORD bytes_written;
word32 err_code; int ret;
DWORD bytes_written; int len;
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); //printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle);
host_handle = scc_ptr->host_handle; host_handle = scc_ptr->host_handle;
if(host_handle == 0) { if(host_handle == 0) {
return; return;
} }
/* Try writing some bytes */ /* Try writing some bytes */
done = 0; done = 0;
while(!done) { while(!done) {
rdptr = scc_ptr->out_rdptr; rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr; wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr) { if(rdptr == wrptr) {
//printf("...rdptr == wrptr\n"); //printf("...rdptr == wrptr\n");
done = 1; done = 1;
break; break;
} }
len = wrptr - rdptr; len = wrptr - rdptr;
if(len < 0) { if(len < 0) {
len = SCC_OUTBUF_SIZE - rdptr; len = SCC_OUTBUF_SIZE - rdptr;
} }
if(len > 32) { if(len > 32) {
len = 32; len = 32;
} }
if(len <= 0) { if(len <= 0) {
done = 1; done = 1;
break; break;
} }
bytes_written = 1; bytes_written = 1;
ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len, ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len,
&bytes_written, NULL); &bytes_written, NULL);
printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret, printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret,
(int)bytes_written, len); (int)bytes_written, len);
err_code = (word32)-1; err_code = (word32)-1;
if(ret == 0) { if(ret == 0) {
err_code = (word32)GetLastError(); err_code = (word32)GetLastError();
printf("WriteFile ret:0, err_code: %08x\n", err_code); printf("WriteFile ret:0, err_code: %08x\n", err_code);
} }
if(ret == 0 || (bytes_written == 0)) { if(ret == 0 || (bytes_written == 0)) {
done = 1; done = 1;
break; break;
} else { } else {
rdptr = rdptr + bytes_written; rdptr = rdptr + bytes_written;
if(rdptr >= SCC_OUTBUF_SIZE) { if(rdptr >= SCC_OUTBUF_SIZE) {
rdptr = rdptr - SCC_OUTBUF_SIZE; rdptr = rdptr - SCC_OUTBUF_SIZE;
} }
scc_ptr->out_rdptr = rdptr; scc_ptr->out_rdptr = rdptr;
} }
} }
} }
#endif #endif

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
// fps shiz // fps shiz
unsigned int lastTime = 0, currentTime, frames; unsigned int lastTime = 0, currentTime, frames;
@ -25,16 +25,16 @@ unsigned int lastTime = 0, currentTime, frames;
#endif #endif
// BITMASKS // BITMASKS
#define ShiftMask 1 #define ShiftMask 1
#define ControlMask 4 #define ControlMask 4
#define LockMask 2 #define LockMask 2
int g_use_shmem = 0; int g_use_shmem = 0;
int g_num_check_input_calls = 0; int g_num_check_input_calls = 0;
int g_check_input_flush_rate = 2; int g_check_input_flush_rate = 2;
int g_win_status_debug = 0; // Current 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_win_status_debug_request = 0; // Desired visibility of status lines.
int g_screen_mdepth = 0; int g_screen_mdepth = 0;
int kb_shift_control_state = 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_palette_8to1624[256];
extern word32 g_a2palette_8to1624[256]; extern word32 g_a2palette_8to1624[256];
extern Kimage g_mainwin_kimage; 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_Window *window; // Declare a pointer
SDL_Renderer *renderer; SDL_Renderer *renderer;
@ -76,124 +76,123 @@ SDL_Texture *overlay_texture; // This is used for scanline simulation. Could be
Uint32 *overlay_pixels; Uint32 *overlay_pixels;
static char *g_clipboard = NULL; // clipboard variables 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 dev_video_init_sdl();
void handle_sdl_key_event(SDL_Event event); void handle_sdl_key_event(SDL_Event event);
void check_input_events_sdl(); void check_input_events_sdl();
int handle_sdl_mouse_motion_event(SDL_Event event); 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] = { int a2_key_to_sdlkeycode[][3] = {
{ 0x35, SDLK_ESCAPE,0 }, { 0x35, SDLK_ESCAPE,0 },
{ 0x7a, SDLK_F1, 0 }, { 0x7a, SDLK_F1, 0 },
{ 0x78, SDLK_F2, 0 }, { 0x78, SDLK_F2, 0 },
{ 0x63, SDLK_F3, 0 }, { 0x63, SDLK_F3, 0 },
{ 0x76, SDLK_F4, 0 }, { 0x76, SDLK_F4, 0 },
{ 0x60, SDLK_F5, 0 }, { 0x60, SDLK_F5, 0 },
{ 0x61, SDLK_F6, 0 }, { 0x61, SDLK_F6, 0 },
{ 0x62, SDLK_F7, 0 }, { 0x62, SDLK_F7, 0 },
{ 0x64, SDLK_F8, 0 }, { 0x64, SDLK_F8, 0 },
{ 0x65, SDLK_F9, 0 }, { 0x65, SDLK_F9, 0 },
{ 0x6d, SDLK_F10, 0 }, { 0x6d, SDLK_F10, 0 },
{ 0x67, SDLK_F11, 0 }, { 0x67, SDLK_F11, 0 },
{ 0x6f, SDLK_F12, 0 }, { 0x6f, SDLK_F12, 0 },
{ 0x69, SDLK_F13, 0 }, { 0x69, SDLK_F13, 0 },
{ 0x6b, SDLK_F14, 0 }, { 0x6b, SDLK_F14, 0 },
{ 0x71, SDLK_F15, 0 }, { 0x71, SDLK_F15, 0 },
{ 0x7f, SDLK_PAUSE, 0 }, { 0x7f, SDLK_PAUSE, 0 },
{ 0x32, '`', '~' }, /* Key number 18? */ { 0x32, '`', '~' }, /* Key number 18? */
{ 0x12, '1', '!' }, { 0x12, '1', '!' },
{ 0x13, '2', '@' }, { 0x13, '2', '@' },
{ 0x14, '3', '#' }, { 0x14, '3', '#' },
{ 0x15, '4', '$' }, { 0x15, '4', '$' },
{ 0x17, '5', '%' }, { 0x17, '5', '%' },
{ 0x16, '6', '^' }, { 0x16, '6', '^' },
{ 0x1a, '7', '&' }, { 0x1a, '7', '&' },
{ 0x1c, '8', '*' }, { 0x1c, '8', '*' },
{ 0x19, '9', '(' }, { 0x19, '9', '(' },
{ 0x1d, '0', ')' }, { 0x1d, '0', ')' },
{ 0x1b, '-', '_' }, { 0x1b, '-', '_' },
{ 0x18, '=', '+' }, { 0x18, '=', '+' },
{ 0x33, SDLK_BACKSPACE, 0 }, { 0x33, SDLK_BACKSPACE, 0 },
{ 0x72, SDLK_INSERT, 0 }, /* Help? XK_Help */ { 0x72, SDLK_INSERT, 0 }, /* Help? XK_Help */
/* { 0x73, XK_Home, 0 }, alias XK_Home to be XK_KP_Equal! */ /* { 0x73, XK_Home, 0 }, alias XK_Home to be XK_KP_Equal! */
{ 0x74, SDLK_PAGEUP, 0 }, { 0x74, SDLK_PAGEUP, 0 },
{ 0x47, SDLK_NUMLOCKCLEAR, 0 }, /* Clear, XK_Clear */ { 0x47, SDLK_NUMLOCKCLEAR, 0 }, /* Clear, XK_Clear */
{ 0x51, SDLK_KP_EQUALS, 0 }, /* Note XK_Home alias! XK_Home */ { 0x51, SDLK_KP_EQUALS, 0 }, /* Note XK_Home alias! XK_Home */
{ 0x4b, SDLK_KP_DIVIDE, 0 }, { 0x4b, SDLK_KP_DIVIDE, 0 },
{ 0x43, SDLK_KP_MULTIPLY, 0 }, { 0x43, SDLK_KP_MULTIPLY, 0 },
{ 0x30, SDLK_TAB, 0 }, { 0x30, SDLK_TAB, 0 },
{ 0x0c, 'q', 'Q' }, { 0x0c, 'q', 'Q' },
{ 0x0d, 'w', 'W' }, { 0x0d, 'w', 'W' },
{ 0x0e, 'e', 'E' }, { 0x0e, 'e', 'E' },
{ 0x0f, 'r', 'R' }, { 0x0f, 'r', 'R' },
{ 0x11, 't', 'T' }, { 0x11, 't', 'T' },
{ 0x10, 'y', 'Y' }, { 0x10, 'y', 'Y' },
{ 0x20, 'u', 'U' }, { 0x20, 'u', 'U' },
{ 0x22, 'i', 'I' }, { 0x22, 'i', 'I' },
{ 0x1f, 'o', 'O' }, { 0x1f, 'o', 'O' },
{ 0x23, 'p', 'P' }, { 0x23, 'p', 'P' },
{ 0x21, '[', '{' }, { 0x21, '[', '{' },
{ 0x1e, ']', '}' }, { 0x1e, ']', '}' },
{ 0x2a, 0x5c, '|' }, /* backslash, bar */ { 0x2a, 0x5c, '|' }, /* backslash, bar */
{ 0x75, SDLK_DELETE, 0 }, { 0x75, SDLK_DELETE, 0 },
{ 0x77, SDLK_END, 0 }, { 0x77, SDLK_END, 0 },
{ 0x79, SDLK_PAGEDOWN, 0 }, { 0x79, SDLK_PAGEDOWN, 0 },
{ 0x59, SDLK_KP_7, SDLK_HOME }, { 0x59, SDLK_KP_7, SDLK_HOME },
{ 0x5b, SDLK_KP_8, SDLK_UP }, { 0x5b, SDLK_KP_8, SDLK_UP },
{ 0x5c, SDLK_KP_9, SDLK_PAGEUP }, { 0x5c, SDLK_KP_9, SDLK_PAGEUP },
{ 0x4e, SDLK_KP_MINUS, 0 }, { 0x4e, SDLK_KP_MINUS, 0 },
{ 0x39, SDLK_CAPSLOCK, 0 }, { 0x39, SDLK_CAPSLOCK, 0 },
{ 0x00, 'a', 'A' }, { 0x00, 'a', 'A' },
{ 0x01, 's', 'S' }, { 0x01, 's', 'S' },
{ 0x02, 'd', 'D' }, { 0x02, 'd', 'D' },
{ 0x03, 'f', 'F' }, { 0x03, 'f', 'F' },
{ 0x05, 'g', 'G' }, { 0x05, 'g', 'G' },
{ 0x04, 'h', 'H' }, { 0x04, 'h', 'H' },
{ 0x26, 'j', 'J' }, { 0x26, 'j', 'J' },
{ 0x28, 'k', 'K' }, { 0x28, 'k', 'K' },
{ 0x25, 'l', 'L' }, { 0x25, 'l', 'L' },
{ 0x29, ';', ':' }, { 0x29, ';', ':' },
{ 0x27, 0x27, '"' }, /* single quote */ { 0x27, 0x27, '"' }, /* single quote */
{ 0x24, SDLK_RETURN, 0 }, { 0x24, SDLK_RETURN, 0 },
{ 0x56, SDLK_KP_4, SDLK_LEFT}, { 0x56, SDLK_KP_4, SDLK_LEFT},
{ 0x57, SDLK_KP_5, 0 }, { 0x57, SDLK_KP_5, 0 },
{ 0x58, SDLK_KP_6, SDLK_RIGHT }, { 0x58, SDLK_KP_6, SDLK_RIGHT },
{ 0x45, SDLK_KP_PLUS, 0 }, { 0x45, SDLK_KP_PLUS, 0 },
{ 0x38, SDLK_LSHIFT, SDLK_RSHIFT }, { 0x38, SDLK_LSHIFT, SDLK_RSHIFT },
{ 0x06, 'z', 'Z' }, { 0x06, 'z', 'Z' },
{ 0x07, 'x', 'X' }, { 0x07, 'x', 'X' },
{ 0x08, 'c', 'C' }, { 0x08, 'c', 'C' },
{ 0x09, 'v', 'V' }, { 0x09, 'v', 'V' },
{ 0x0b, 'b', 'B' }, { 0x0b, 'b', 'B' },
{ 0x2d, 'n', 'N' }, { 0x2d, 'n', 'N' },
{ 0x2e, 'm', 'M' }, { 0x2e, 'm', 'M' },
{ 0x2b, ',', '<' }, { 0x2b, ',', '<' },
{ 0x2f, '.', '>' }, { 0x2f, '.', '>' },
{ 0x2c, '/', '?' }, { 0x2c, '/', '?' },
{ 0x3e, SDLK_UP, 0 }, { 0x3e, SDLK_UP, 0 },
{ 0x53, SDLK_KP_1, 0 }, { 0x53, SDLK_KP_1, 0 },
{ 0x54, SDLK_KP_2, SDLK_DOWN }, { 0x54, SDLK_KP_2, SDLK_DOWN },
{ 0x55, SDLK_KP_3, SDLK_PAGEDOWN }, { 0x55, SDLK_KP_3, SDLK_PAGEDOWN },
{ 0x36, SDLK_RCTRL, SDLK_LCTRL }, { 0x36, SDLK_RCTRL, SDLK_LCTRL },
{ 0x3a, SDLK_LALT, SDLK_RALT }, /* Option */ { 0x3a, SDLK_LALT, SDLK_RALT }, /* Option */
{ 0x37, SDLK_LGUI, SDLK_RGUI }, /* Command */ { 0x37, SDLK_LGUI, SDLK_RGUI }, /* Command */
{ 0x31, ' ', 0 }, { 0x31, ' ', 0 },
{ 0x3b, SDLK_LEFT, 0 }, { 0x3b, SDLK_LEFT, 0 },
{ 0x3d, SDLK_DOWN, 0 }, { 0x3d, SDLK_DOWN, 0 },
{ 0x3c, SDLK_RIGHT, 0 }, { 0x3c, SDLK_RIGHT, 0 },
{ 0x52, SDLK_KP_0, 0 }, { 0x52, SDLK_KP_0, 0 },
{ 0x41, SDLK_KP_PERIOD, 0 }, { 0x41, SDLK_KP_PERIOD, 0 },
{ 0x4c, SDLK_KP_ENTER, 0 }, { 0x4c, SDLK_KP_ENTER, 0 },
{ -1, -1, -1 } { -1, -1, -1 }
}; };
int main(int argc, char **argv) int main(int argc, char **argv) {
{
return gsplusmain(argc, argv); return gsplusmain(argc, argv);
} }
@ -225,12 +224,12 @@ SDL_bool IsFullScreen(SDL_Window *win) {
void dev_video_init() { void dev_video_init() {
word32 lores_col; word32 lores_col;
// build keycode map ?? // build keycode map ??
g_num_a2_keycodes = 0; g_num_a2_keycodes = 0;
int i; int i;
int keycode; int keycode;
for(i = 0; i < 0x7f; i++) { for(i = 0; i < 0x7f; i++) {
keycode = a2_key_to_sdlkeycode[i][0]; keycode = a2_key_to_sdlkeycode[i][0];
@ -310,15 +309,14 @@ void dev_video_init_sdl() {
window = SDL_CreateWindow( window = SDL_CreateWindow(
window_title, // window title (GSport vX.X) window_title, // window title (GSport vX.X)
// SDL_WINDOWPOS_UNDEFINED, // initial x position startx,
// SDL_WINDOWPOS_UNDEFINED, // initial y position starty,
startx, starty,
BASE_WINDOW_WIDTH, // width, in pixels BASE_WINDOW_WIDTH, // width, in pixels
X_A2_WINDOW_HEIGHT, // height, in pixels X_A2_WINDOW_HEIGHT, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below SDL_WINDOW_OPENGL // flags - see below
| more_flags | more_flags
); );
// Check that the window was successfully created // 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); SDL_RenderSetLogicalSize(renderer, BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT);
texture = SDL_CreateTexture(renderer, texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_STREAMING,
BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT); BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT);
// The window is open: could enter program loop here (see SDL_PollEvent()) // The window is open: could enter program loop here (see SDL_PollEvent())
//overlay test //overlay test
overlay_texture = SDL_CreateTexture(renderer, overlay_texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_STREAMING,
BASE_WINDOW_WIDTH, BASE_WINDOW_WIDTH,
X_A2_WINDOW_HEIGHT); X_A2_WINDOW_HEIGHT);
SDL_SetTextureBlendMode(overlay_texture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(overlay_texture, SDL_BLENDMODE_BLEND);
overlay_pixels = malloc(BASE_WINDOW_WIDTH*X_A2_WINDOW_HEIGHT*sizeof(Uint32)); 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 // 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) { 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; byte *src_ptr;
int pixel_size = 4; int pixel_size = 4;
@ -436,9 +425,9 @@ void set_refresh_needed() {
void x_get_kimage(Kimage *kimage_ptr) { void x_get_kimage(Kimage *kimage_ptr) {
byte *data; byte *data;
int width; int width;
int height; int height;
int depth; int depth;
width = kimage_ptr->width_req; width = kimage_ptr->width_req;
height = kimage_ptr->height; height = kimage_ptr->height;
@ -455,7 +444,7 @@ void check_input_events() {
void check_input_events_sdl() { void check_input_events_sdl() {
int motion = 0; int motion = 0;
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
@ -463,7 +452,7 @@ void check_input_events_sdl() {
if (event.type == SDL_WINDOWEVENT) { if (event.type == SDL_WINDOWEVENT) {
set_refresh_needed(); set_refresh_needed();
} }
switch( event.type ){ switch( event.type ) {
case SDL_KEYDOWN: case SDL_KEYDOWN:
case SDL_KEYUP: case SDL_KEYUP:
handle_sdl_key_event(event); handle_sdl_key_event(event);
@ -486,7 +475,7 @@ void check_input_events_sdl() {
cfg_inspect_maybe_insert_file(file, 0); cfg_inspect_maybe_insert_file(file, 0);
SDL_free(file); SDL_free(file);
} }
break; break;
default: default:
break; break;
} }
@ -495,7 +484,7 @@ void check_input_events_sdl() {
int sdl_keysym_to_a2code(int keysym, int is_up) { int sdl_keysym_to_a2code(int keysym, int is_up) {
int i; int i;
if(keysym == 0) { if(keysym == 0) {
return -1; return -1;
@ -526,7 +515,7 @@ int sdl_keysym_to_a2code(int keysym, int is_up) {
/* Look up Apple 2 keycode */ /* Look up Apple 2 keycode */
for(i = g_num_a2_keycodes - 1; i >= 0; i--) { for(i = g_num_a2_keycodes - 1; i >= 0; i--) {
if((keysym == a2_key_to_sdlkeycode[i][1]) || 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]; 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) { void handle_sdl_key_event(SDL_Event event) {
int state_xor; int state_xor;
int state = 0; int state = 0;
int is_up; int is_up;
int mod = event.key.keysym.mod; 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 // when mod key is first press, comes as event, otherwise just a modifier
if( mod & KMOD_LCTRL || mod & KMOD_RCTRL || if( mod & KMOD_LCTRL || mod & KMOD_RCTRL ||
event.type == (SDL_KEYDOWN && (event.key.keysym.sym == SDLK_LCTRL || event.key.keysym.sym == SDLK_RCTRL))) { event.type == (SDL_KEYDOWN && (event.key.keysym.sym == SDLK_LCTRL || event.key.keysym.sym == SDLK_RCTRL))) {
state = state | ControlMask; state = state | ControlMask;
} }
if( (mod & KMOD_LSHIFT) || (mod & KMOD_RSHIFT) || 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; state = state | ShiftMask;
} }
if( mod & KMOD_CAPS) { if( mod & KMOD_CAPS) {
@ -581,7 +570,7 @@ void handle_sdl_key_event(SDL_Event event) {
if (event.type == SDL_KEYUP) { if (event.type == SDL_KEYUP) {
is_up = 1; is_up = 1;
} }
switch( event.key.keysym.sym ){ switch( event.key.keysym.sym ) {
case SDLK_F11: case SDLK_F11:
if (kb_shift_control_state & ShiftMask) { // SHIFT+F11 if (kb_shift_control_state & ShiftMask) { // SHIFT+F11
if (!is_up) { if (!is_up) {
@ -623,7 +612,7 @@ int handle_sdl_mouse_motion_event(SDL_Event event) {
x = event.motion.x - BASE_MARGIN_LEFT; x = event.motion.x - BASE_MARGIN_LEFT;
y = event.motion.y - BASE_MARGIN_TOP; y = event.motion.y - BASE_MARGIN_TOP;
if (event.type == SDL_MOUSEBUTTONUP) { 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 { } else {
return update_mouse(x, y, event.motion.state, event.motion.state &7 ); return update_mouse(x, y, event.motion.state, event.motion.state &7 );
} }
@ -708,13 +697,13 @@ void x_take_screenshot() {
SDL_FreeSurface(sshot); SDL_FreeSurface(sshot);
SDL_Surface *s = SDL_CreateRGBSurface(0, BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); SDL_Surface *s = SDL_CreateRGBSurface(0, BASE_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
if (s) { if (s) {
SDL_Surface * image = SDL_LoadBMP("screenshot.bmp"); SDL_Surface * image = SDL_LoadBMP("screenshot.bmp");
IMG_SavePNG(image, screenshot_filename); IMG_SavePNG(image, screenshot_filename);
SDL_FreeSurface(image); SDL_FreeSurface(image);
}
SDL_FreeSurface(s);
} }
SDL_FreeSurface(s);
}
void clipboard_paste(void) { void clipboard_paste(void) {
@ -741,7 +730,7 @@ int clipboard_get_char(void) {
char c; char c;
if (!g_clipboard) if (!g_clipboard)
return 0; return 0;
/* skip utf-8 characters. */ /* skip utf-8 characters. */
do { do {
@ -750,7 +739,7 @@ int clipboard_get_char(void) {
/* windows -- skip the \n in \r\n. */ /* windows -- skip the \n in \r\n. */
if (c == '\r' && g_clipboard[g_clipboard_pos] == '\n') if (c == '\r' && g_clipboard[g_clipboard_pos] == '\n')
g_clipboard_pos++; g_clipboard_pos++;
/* everybody else -- convert \n to \r */ /* everybody else -- convert \n to \r */
if (c == '\n') c = '\r'; if (c == '\n') c = '\r';
@ -788,7 +777,7 @@ void x_auto_repeat_off(int must) { }
void x_release_kimage(Kimage* kimage_ptr) { } void x_release_kimage(Kimage* kimage_ptr) { }
// OG Addding ratio // OG Addding ratio
int x_calc_ratio(float x,float y) { return 1; } 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_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() { }

View File

@ -1,18 +1,18 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "SDL.h" #include "SDL.h"
#include "defc.h" #include "defc.h"
#include "glog.h" #include "glog.h"
#include "sound.h" #include "sound.h"
#include <assert.h> #include <assert.h>
extern word32 *g_sound_shm_addr; extern word32 *g_sound_shm_addr;
extern int g_sound_shm_pos; extern int g_sound_shm_pos;
extern int g_audio_enable; extern int g_audio_enable;
extern int g_preferred_rate; extern int g_preferred_rate;
static byte *playbuf = 0; static byte *playbuf = 0;
@ -29,187 +29,179 @@ static int g_zeroes_seen;
SDL_AudioDeviceID dev = 0; SDL_AudioDeviceID dev = 0;
void sdlsnd_init(word32 *shmaddr) void sdlsnd_init(word32 *shmaddr) {
{
if (SDL_Init(SDL_INIT_AUDIO) < 0) { if (SDL_Init(SDL_INIT_AUDIO) < 0) {
glog("Could not initialize SDL2 audio"); glog("Could not initialize SDL2 audio");
g_audio_enable = 0; g_audio_enable = 0;
} else { } else {
glog("SDL2 audio initialized"); glog("SDL2 audio initialized");
} }
child_sound_loop(-1, -1, shmaddr); child_sound_loop(-1, -1, shmaddr);
return; return;
} }
void void sound_write_sdl(int real_samps, int size) {
sound_write_sdl(int real_samps, int size)
{
#ifdef HAVE_SDL #ifdef HAVE_SDL
int shm_read; int shm_read;
if (real_samps) { if (real_samps) {
shm_read = (g_sound_shm_pos - size + SOUND_SHM_SAMP_SIZE)%SOUND_SHM_SAMP_SIZE; shm_read = (g_sound_shm_pos - size + SOUND_SHM_SAMP_SIZE)%SOUND_SHM_SAMP_SIZE;
SDL_LockAudioDevice(dev); SDL_LockAudioDevice(dev);
while(size > 0) { while(size > 0) {
if(g_playbuf_buffered >= snd_buf) { if(g_playbuf_buffered >= snd_buf) {
printf("sound_write_sdl failed @%d, %d buffered, %d samples skipped\n",snd_write,g_playbuf_buffered, size); printf("sound_write_sdl failed @%d, %d buffered, %d samples skipped\n",snd_write,g_playbuf_buffered, size);
shm_read += size; shm_read += size;
shm_read %= SOUND_SHM_SAMP_SIZE; shm_read %= SOUND_SHM_SAMP_SIZE;
size = 0; size = 0;
} else { } else {
((word32*)playbuf)[snd_write/SAMPLE_CHAN_SIZE] = g_sound_shm_addr[shm_read]; ((word32*)playbuf)[snd_write/SAMPLE_CHAN_SIZE] = g_sound_shm_addr[shm_read];
shm_read++; shm_read++;
if (shm_read >= SOUND_SHM_SAMP_SIZE) if (shm_read >= SOUND_SHM_SAMP_SIZE)
shm_read = 0; shm_read = 0;
snd_write += SAMPLE_CHAN_SIZE; snd_write += SAMPLE_CHAN_SIZE;
if (snd_write >= snd_buf) if (snd_write >= snd_buf)
snd_write = 0; snd_write = 0;
size--; size--;
g_playbuf_buffered += SAMPLE_CHAN_SIZE; g_playbuf_buffered += SAMPLE_CHAN_SIZE;
} }
} }
assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf); assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf);
assert(g_sound_shm_pos == shm_read); assert(g_sound_shm_pos == shm_read);
SDL_UnlockAudioDevice(dev); SDL_UnlockAudioDevice(dev);
} }
if(g_sound_paused && (g_playbuf_buffered > 0)) { if(g_sound_paused && (g_playbuf_buffered > 0)) {
glogf("Unpausing sound, %d buffered",g_playbuf_buffered); glogf("Unpausing sound, %d buffered",g_playbuf_buffered);
g_sound_paused = 0; g_sound_paused = 0;
SDL_PauseAudioDevice(dev, 0); SDL_PauseAudioDevice(dev, 0);
} }
if(!g_sound_paused && (g_playbuf_buffered <= 0)) { if(!g_sound_paused && (g_playbuf_buffered <= 0)) {
glog("Pausing sound"); glog("Pausing sound");
g_sound_paused = 1; g_sound_paused = 1;
SDL_PauseAudioDevice(dev, 1); SDL_PauseAudioDevice(dev, 1);
} }
#endif #endif
} }
#ifdef HAVE_SDL #ifdef HAVE_SDL
/* Callback for sound */ /* Callback for sound */
static void _snd_callback(void* userdata, Uint8 *stream, int len) static void _snd_callback(void* userdata, Uint8 *stream, int len) {
{ int i;
int i; /* Slurp off the play buffer */
/* Slurp off the play buffer */ assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf);
assert((snd_buf+snd_write - snd_read)%snd_buf == g_playbuf_buffered%snd_buf); /*printf("slurp %d, %d buffered\n",len, g_playbuf_buffered);*/
/*printf("slurp %d, %d buffered\n",len, g_playbuf_buffered);*/ for(i = 0; i < len; ++i) {
for(i = 0; i < len; ++i) { if(g_playbuf_buffered <= 0) {
if(g_playbuf_buffered <= 0) { stream[i] = 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;
} else { } 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 0
if(spec.channels != wanted.channels) { if (g_playbuf_buffered <= 0) {
glogf("SDL2 Warning, couldn't get stereo audio format!"); printf("snd_callback: buffer empty, Pausing sound\n");
//goto snd_error; g_sound_paused = 1;
} SDL_PauseAudio(1);
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 #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 #ifdef HAVE_SDL
SDL_CloseAudioDevice(dev); long rate;
if(playbuf) SDL_AudioSpec wanted;
free((void*)playbuf);
playbuf = 0; 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 #endif
} }

View File

@ -1,9 +1,9 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include <assert.h> #include <assert.h>
#include "defc.h" #include "defc.h"
@ -18,7 +18,7 @@ extern int g_audio_rate;
unsigned int __stdcall child_sound_loop_win32(void *param); unsigned int __stdcall child_sound_loop_win32(void *param);
void check_wave_error(int res, char *str); 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]; //WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
@ -27,7 +27,7 @@ extern int g_audio_enable;
extern word32 *g_sound_shm_addr; extern word32 *g_sound_shm_addr;
extern int g_preferred_rate; extern int g_preferred_rate;
int g_sdlsnd_buflen = 0x1000; int g_sdlsnd_buflen = 0x1000;
word32 *bptr = NULL; word32 *bptr = NULL;
int g_sdlsnd_write_idx; int g_sdlsnd_write_idx;
int g_sdlsnd_read_idx; int g_sdlsnd_read_idx;
@ -55,13 +55,12 @@ static void sound_write_sdl(int real_samps, int size);
#endif #endif
void sdlsnd_init(word32 *shmaddr) void sdlsnd_init(word32 *shmaddr) {
{
printf("sdlsnd_init\n"); printf("sdlsnd_init\n");
if (SDL_Init(SDL_INIT_AUDIO) < 0) { if (SDL_Init(SDL_INIT_AUDIO) < 0) {
printf("Cannot initialize SDL audio\n"); printf("Cannot initialize SDL audio\n");
g_audio_enable = 0; g_audio_enable = 0;
} }
child_sound_loop(-1, -1, shmaddr); child_sound_loop(-1, -1, shmaddr);
return; return;
@ -70,17 +69,15 @@ void sdlsnd_init(word32 *shmaddr)
void void win32snd_init(word32 *shmaddr) {
win32snd_init(word32 *shmaddr) printf("win32snd_init\n");
{ child_sound_loop(-1, -1, 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 */ /* code */
//printf(" sdl_s_a %d\t 0x%08x ",size, &ptr); //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 */ /* Only play if we have data left */
/* if ( g_playbuf_buffered == 0) { /* if ( g_playbuf_buffered == 0) {
return; return;
} }
*/ */
for(int i = 0; i < len; ++i) { for(int i = 0; i < len; ++i) {
if(g_playbuf_buffered <= 0) { if(g_playbuf_buffered <= 0) {
stream[i] = 0; stream[i] = 0;
} else { } else {
stream[i] = bptr[g_sdlsnd_read_idx++]; stream[i] = bptr[g_sdlsnd_read_idx++];
if(g_sdlsnd_read_idx == g_sdlsnd_buflen) if(g_sdlsnd_read_idx == g_sdlsnd_buflen)
g_sdlsnd_read_idx = 0; g_sdlsnd_read_idx = 0;
g_playbuf_buffered--; g_playbuf_buffered--;
} }
} }
return; return;
@ -128,15 +125,15 @@ void handle_sdl_snd(void *userdata, Uint8 *stream, int len) {
g_playbuf_buffered -= len; g_playbuf_buffered -= len;
} else { } else {
/* /*
int top_len = 0; int top_len = 0;
top_len = g_sdlsnd_buflen - g_sdlsnd_read_idx; top_len = g_sdlsnd_buflen - g_sdlsnd_read_idx;
SDL_memcpy (stream, &bptr[g_sdlsnd_read_idx], top_len); SDL_memcpy (stream, &bptr[g_sdlsnd_read_idx], top_len);
g_sdlsnd_read_idx = 0; g_sdlsnd_read_idx = 0;
g_playbuf_buffered -= top_len; g_playbuf_buffered -= top_len;
// SDL_memcpy (stream+top_len, bptr[g_sdlsnd_read_idx], len-top_len); // SDL_memcpy (stream+top_len, bptr[g_sdlsnd_read_idx], len-top_len);
g_sdlsnd_read_idx += len-top_len; g_sdlsnd_read_idx += len-top_len;
g_playbuf_buffered -= len-top_len; g_playbuf_buffered -= len-top_len;
*/ */
} }
//SDL_MixAudio(stream, pointer, len, SDL_MIX_MAXVOLUME); //SDL_MixAudio(stream, pointer, len, SDL_MIX_MAXVOLUME);
@ -144,9 +141,7 @@ void handle_sdl_snd(void *userdata, Uint8 *stream, int len) {
} }
void void child_sound_init_sdl() {
child_sound_init_sdl()
{
printf("child_sound_init_sdl"); printf("child_sound_init_sdl");
SDL_memset(&want, 0, sizeof(want)); // or SDL_zero(want) 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); dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (dev == 0) { if (dev == 0) {
printf("Failed to open audio: %s\n", SDL_GetError()); printf("Failed to open audio: %s\n", SDL_GetError());
} else { } else {
if (have.format != want.format) { // we let this one thing change. if (have.format != want.format) { // we let this one thing change.
printf("We didn't get Float32 audio format.\n"); printf("We didn't get Float32 audio format.\n");
} }
} }
@ -185,16 +180,15 @@ child_sound_init_sdl()
SDL_PauseAudioDevice(dev, 0); // start audio playing. 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); 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 void sdlsnd_shutdown() {
sdlsnd_shutdown() {
//SDL_Delay(5000); // let the audio callback play some sound for 5 seconds. //SDL_Delay(5000); // let the audio callback play some sound for 5 seconds.
SDL_CloseAudioDevice(dev); SDL_CloseAudioDevice(dev);
printf("sdlsnd_shutdown"); 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #include "defc.h"
#include "sound.h" #include "sound.h"
@ -21,7 +21,7 @@ long sound_init_device_sdl();
# include <sys/soundcard.h> # include <sys/soundcard.h>
#endif #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 <sys/socket.h>
# include <netinet/in.h> # include <netinet/in.h>
#endif #endif
@ -34,22 +34,22 @@ extern int Verbose;
extern int g_audio_rate; extern int g_audio_rate;
int g_preferred_rate = 48000; int g_preferred_rate = 48000;
int g_audio_socket = -1; int g_audio_socket = -1;
int g_bytes_written = 0; int g_bytes_written = 0;
#define ZERO_BUF_SIZE 2048 #define ZERO_BUF_SIZE 2048
word32 g_snd_zero_buf[ZERO_BUF_SIZE]; word32 g_snd_zero_buf[ZERO_BUF_SIZE];
#define ZERO_PAUSE_SAFETY_SAMPS (g_audio_rate >> 5) #define ZERO_PAUSE_SAFETY_SAMPS (g_audio_rate >> 5)
#define ZERO_PAUSE_NUM_SAMPS (4*g_audio_rate) #define ZERO_PAUSE_NUM_SAMPS (4*g_audio_rate)
int g_zeroes_buffered = 0; int g_zeroes_buffered = 0;
int g_zeroes_seen = 0; int g_zeroes_seen = 0;
int g_sound_paused = 0; int g_sound_paused = 0;
int g_childsnd_vbl = 0; int g_childsnd_vbl = 0;
int g_childsnd_pos = 0; int g_childsnd_pos = 0;
word32 *g_childsnd_shm_addr = 0; word32 *g_childsnd_shm_addr = 0;
void child_sound_init_linux(); void child_sound_init_linux();
@ -59,364 +59,352 @@ void child_sound_init_mac();
void child_sound_init_sdl(); void child_sound_init_sdl();
long sound_init_device_sdl(); long sound_init_device_sdl();
void void reliable_buf_write(word32 *shm_addr, int pos, int size) {
reliable_buf_write(word32 *shm_addr, int pos, int size) byte *ptr;
{ int ret = 0;
byte *ptr;
int ret = 0;
if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE || if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE ||
size > SOUND_SHM_SAMP_SIZE || size > SOUND_SHM_SAMP_SIZE ||
(pos + size) > SOUND_SHM_SAMP_SIZE) { (pos + size) > SOUND_SHM_SAMP_SIZE) {
printf("reliable_buf_write: pos: %04x, size: %04x\n", pos, size); printf("reliable_buf_write: pos: %04x, size: %04x\n", pos, size);
exit(1); exit(1);
} }
ptr = (byte *)&(shm_addr[pos]); ptr = (byte *)&(shm_addr[pos]);
size = size * 4; size = size * 4;
while(size > 0) { while(size > 0) {
#if defined(HAVE_SDL) #if defined(HAVE_SDL)
//ret = sdl_send_audio(ptr, size); //ret = sdl_send_audio(ptr, size);
#elif defined(WIN_SOUND) #elif defined(WIN_SOUND)
ret = win32_send_audio(ptr, size); ret = win32_send_audio(ptr, size);
#elif defined(MAC) && !defined(HAVE_SDL) #elif defined(MAC) && !defined(HAVE_SDL)
ret = mac_send_audio(ptr, size); ret = mac_send_audio(ptr, size);
#else #else
ret = write(g_audio_socket, ptr, size); ret = write(g_audio_socket, ptr, size);
#endif #endif
if(ret < 0) { if(ret < 0) {
printf("audio write, errno: %d\n", errno); printf("audio write, errno: %d\n", errno);
exit(1); exit(1);
} }
size = size - ret; size = size - ret;
ptr += ret; ptr += ret;
g_bytes_written += ret; g_bytes_written += ret;
} }
} }
void void reliable_zero_write(int amt) {
reliable_zero_write(int amt) int len;
{
int len;
while(amt > 0) { while(amt > 0) {
len = MIN(amt, ZERO_BUF_SIZE); len = MIN(amt, ZERO_BUF_SIZE);
reliable_buf_write(g_snd_zero_buf, 0, len); reliable_buf_write(g_snd_zero_buf, 0, len);
amt -= len; amt -= len;
} }
} }
void void child_sound_loop(int read_fd, int write_fd, word32 *shm_addr) {
child_sound_loop(int read_fd, int write_fd, word32 *shm_addr) word32 tmp;
{ int ret;
word32 tmp;
int ret;
g_audio_rate = g_preferred_rate; g_audio_rate = g_preferred_rate;
g_zeroes_buffered = 0; g_zeroes_buffered = 0;
g_zeroes_seen = 0; g_zeroes_seen = 0;
g_sound_paused = 0; g_sound_paused = 0;
g_childsnd_pos = 0; g_childsnd_pos = 0;
g_childsnd_vbl = 0; g_childsnd_vbl = 0;
g_childsnd_shm_addr = shm_addr; g_childsnd_shm_addr = shm_addr;
#if defined(HAVE_SDL) #if defined(HAVE_SDL)
//child_sound_init_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; return;
#elif defined(__linux__) || defined(OSS) #elif defined(__linux__) || defined(OSS)
child_sound_init_linux(); child_sound_init_linux();
#elif HPUX #elif HPUX
child_sound_init_hpdev(); child_sound_init_hpdev();
#elif WIN_SOUND #elif WIN_SOUND
child_sound_init_win32(); child_sound_init_win32();
return; return;
#elif defined(MAC) && !defined(HAVE_SDL) #elif defined(MAC) && !defined(HAVE_SDL)
child_sound_init_mac(); child_sound_init_mac();
return; return;
#endif #endif
doc_printf("Child pipe fd: %d\n", read_fd); doc_printf("Child pipe fd: %d\n", read_fd);
tmp = g_audio_rate; tmp = g_audio_rate;
ret = write(write_fd, &tmp, 4); ret = write(write_fd, &tmp, 4);
if(ret != 4) { if(ret != 4) {
printf("Unable to send back audio rate to parent\n"); printf("Unable to send back audio rate to parent\n");
printf("ret: %d fd: %d, errno: %d\n", ret, write_fd, errno); printf("ret: %d fd: %d, errno: %d\n", ret, write_fd, errno);
exit(1); exit(1);
} }
printf("Wrote to fd %d the audio rate\n", write_fd); printf("Wrote to fd %d the audio rate\n", write_fd);
close(write_fd); close(write_fd);
while(1) { while(1) {
errno = 0; errno = 0;
ret = read(read_fd, (char*)&tmp, 4); ret = read(read_fd, (char*)&tmp, 4);
if(ret <= 0) { if(ret <= 0) {
printf("child dying from ret: %d, errno: %d\n", printf("child dying from ret: %d, errno: %d\n",
ret, errno); ret, errno);
break; break;
} }
child_sound_playit(tmp); child_sound_playit(tmp);
} }
#ifdef HPUX #ifdef HPUX
ioctl(g_audio_socket, AUDIO_DRAIN, 0); ioctl(g_audio_socket, AUDIO_DRAIN, 0);
#endif #endif
close(g_audio_socket); close(g_audio_socket);
exit(0); exit(0);
} }
// called by sound.c:send_sound() // called by sound.c:send_sound()
void void child_sound_playit(word32 tmp) {
child_sound_playit(word32 tmp) int size;
{
int size;
size = tmp & 0xffffff; size = tmp & 0xffffff;
if((tmp >> 24) == 0xa2) { if((tmp >> 24) == 0xa2) {
/* play sound here */ /* play sound here */
#if 0 #if 0
g_childsnd_pos += g_zeroes_buffered; g_childsnd_pos += g_zeroes_buffered;
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) { while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE; g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
} }
#endif #endif
if(g_zeroes_buffered) { if(g_zeroes_buffered) {
reliable_zero_write(g_zeroes_buffered); reliable_zero_write(g_zeroes_buffered);
} }
g_zeroes_buffered = 0; g_zeroes_buffered = 0;
g_zeroes_seen = 0; g_zeroes_seen = 0;
// only write up to end of buffer // only write up to end of buffer
if((size + g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) { if((size + g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) {
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos, reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos,
SOUND_SHM_SAMP_SIZE - g_childsnd_pos); SOUND_SHM_SAMP_SIZE - g_childsnd_pos);
size = (g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE; size = (g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE;
g_childsnd_pos = 0; 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) { if(g_sound_paused) {
glogf("Unpausing sound, zb: %d\n", g_zeroes_buffered); glogf("Unpausing sound, zb: %d\n", g_zeroes_buffered);
g_sound_paused = 0; g_sound_paused = 0;
} }
} else if((tmp >> 24) == 0xa1) { } else if((tmp >> 24) == 0xa1) {
if(g_sound_paused) { if(g_sound_paused) {
if(g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) { if(g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) {
g_zeroes_buffered += size; g_zeroes_buffered += size;
} }
} else { } else {
/* not paused, send it through */ /* not paused, send it through */
g_zeroes_seen += size; g_zeroes_seen += size;
reliable_zero_write(size); reliable_zero_write(size);
if(g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) { if(g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) {
glog("Pausing sound"); glog("Pausing sound");
g_sound_paused = 1; g_sound_paused = 1;
} }
} }
} else { } else {
printf("tmp received bad: %08x\n", tmp); printf("tmp received bad: %08x\n", tmp);
exit(3); exit(3);
} }
g_childsnd_pos += size; g_childsnd_pos += size;
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) { while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE; g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
} }
g_childsnd_vbl++; g_childsnd_vbl++;
if(g_childsnd_vbl >= 60) { if(g_childsnd_vbl >= 60) {
g_childsnd_vbl = 0; g_childsnd_vbl = 0;
g_bytes_written = 0; g_bytes_written = 0;
} }
} }
#ifdef HPUX #ifdef HPUX
void void child_sound_init_hpdev() {
child_sound_init_hpdev() struct audio_describe audio_descr;
{ int output_channel;
struct audio_describe audio_descr; char *str;
int output_channel; int speaker;
char *str; int ret;
int speaker; int i;
int ret;
int i;
g_audio_socket = open("/dev/audio", O_WRONLY, 0); g_audio_socket = open("/dev/audio", O_WRONLY, 0);
if(g_audio_socket < 0) { if(g_audio_socket < 0) {
printf("open /dev/audio failed, ret: %d, errno:%d\n", printf("open /dev/audio failed, ret: %d, errno:%d\n",
g_audio_socket, errno); g_audio_socket, errno);
exit(1); exit(1);
} }
ret = ioctl(g_audio_socket, AUDIO_DESCRIBE, &audio_descr); ret = ioctl(g_audio_socket, AUDIO_DESCRIBE, &audio_descr);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_DESCRIBE failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_DESCRIBE failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
for(i = 0; i < audio_descr.nrates; i++) { for(i = 0; i < audio_descr.nrates; i++) {
printf("Audio rate[%d] = %d\n", i, printf("Audio rate[%d] = %d\n", i,
audio_descr.sample_rate[i]); audio_descr.sample_rate[i]);
} }
ret = ioctl(g_audio_socket, AUDIO_SET_DATA_FORMAT, ret = ioctl(g_audio_socket, AUDIO_SET_DATA_FORMAT,
AUDIO_FORMAT_LINEAR16BIT); AUDIO_FORMAT_LINEAR16BIT);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_SET_DATA_FORMAT failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_SET_DATA_FORMAT failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
ret = ioctl(g_audio_socket, AUDIO_SET_CHANNELS, NUM_CHANNELS); ret = ioctl(g_audio_socket, AUDIO_SET_CHANNELS, NUM_CHANNELS);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_SET_CHANNELS failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_SET_CHANNELS failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
ret = ioctl(g_audio_socket, AUDIO_SET_TXBUFSIZE, 16*1024); ret = ioctl(g_audio_socket, AUDIO_SET_TXBUFSIZE, 16*1024);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_SET_TXBUFSIZE failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_SET_TXBUFSIZE failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
ret = ioctl(g_audio_socket, AUDIO_SET_SAMPLE_RATE, g_audio_rate); ret = ioctl(g_audio_socket, AUDIO_SET_SAMPLE_RATE, g_audio_rate);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_SET_SAMPLE_RATE failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_SET_SAMPLE_RATE failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
ret = ioctl(g_audio_socket, AUDIO_GET_OUTPUT, &output_channel); ret = ioctl(g_audio_socket, AUDIO_GET_OUTPUT, &output_channel);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_GET_OUTPUT failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_GET_OUTPUT failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
speaker = 1; speaker = 1;
str = getenv("SPEAKER"); str = getenv("SPEAKER");
if(str) { if(str) {
if(str[0] != 'i' && str[0] != 'I') { if(str[0] != 'i' && str[0] != 'I') {
speaker = 0; speaker = 0;
} }
} }
if(speaker) { if(speaker) {
printf("Sending sound to internal speaker\n"); printf("Sending sound to internal speaker\n");
output_channel |= AUDIO_OUT_SPEAKER; output_channel |= AUDIO_OUT_SPEAKER;
} else { } else {
printf("Sending sound to external jack\n"); printf("Sending sound to external jack\n");
output_channel &= (~AUDIO_OUT_SPEAKER); output_channel &= (~AUDIO_OUT_SPEAKER);
output_channel |= AUDIO_OUT_HEADPHONE; output_channel |= AUDIO_OUT_HEADPHONE;
} }
ret = ioctl(g_audio_socket, AUDIO_SET_OUTPUT, output_channel); ret = ioctl(g_audio_socket, AUDIO_SET_OUTPUT, output_channel);
if(ret < 0) { if(ret < 0) {
printf("ioctl AUDIO_SET_OUTPUT failed, ret:%d, errno:%d\n", printf("ioctl AUDIO_SET_OUTPUT failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
} }
#endif /* HPUX */ #endif /* HPUX */
#if defined(__linux__) || defined(OSS) #if defined(__linux__) || defined(OSS)
void void child_sound_init_linux() {
child_sound_init_linux() int stereo;
{ int sample_size;
int stereo; int rate;
int sample_size; int fragment;
int rate; int fmt;
int fragment; int ret;
int fmt;
int ret;
g_audio_socket = open("/dev/dsp", O_WRONLY, 0); g_audio_socket = open("/dev/dsp", O_WRONLY, 0);
if(g_audio_socket < 0) { if(g_audio_socket < 0) {
printf("open /dev/dsp failed, ret: %d, errno:%d\n", printf("open /dev/dsp failed, ret: %d, errno:%d\n",
g_audio_socket, errno); g_audio_socket, errno);
exit(1); exit(1);
} }
fragment = 0x00200009; fragment = 0x00200009;
#if 0 #if 0
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFRAGMENT, &fragment); ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFRAGMENT, &fragment);
if(ret < 0) { if(ret < 0) {
printf("ioctl SETFRAGEMNT failed, ret:%d, errno:%d\n", printf("ioctl SETFRAGEMNT failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
#endif #endif
sample_size = 16; sample_size = 16;
ret = ioctl(g_audio_socket, SNDCTL_DSP_SAMPLESIZE, &sample_size); ret = ioctl(g_audio_socket, SNDCTL_DSP_SAMPLESIZE, &sample_size);
if(ret < 0) { if(ret < 0) {
printf("ioctl SNDCTL_DSP_SAMPLESIZE failed, ret:%d, errno:%d\n", printf("ioctl SNDCTL_DSP_SAMPLESIZE failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
#if defined(GSPLUS_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command #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 #else
fmt = AFMT_S16_BE; fmt = AFMT_S16_BE;
#endif #endif
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFMT, &fmt); ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFMT, &fmt);
if(ret < 0) { if(ret < 0) {
printf("ioctl SNDCTL_DSP_SETFMT failed, ret:%d, errno:%d\n", printf("ioctl SNDCTL_DSP_SETFMT failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
stereo = 1; stereo = 1;
ret = ioctl(g_audio_socket, SNDCTL_DSP_STEREO, &stereo); ret = ioctl(g_audio_socket, SNDCTL_DSP_STEREO, &stereo);
if(ret < 0) { if(ret < 0) {
printf("ioctl SNDCTL_DSP_STEREO failed, ret:%d, errno:%d\n", printf("ioctl SNDCTL_DSP_STEREO failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
rate = g_audio_rate; rate = g_audio_rate;
ret = ioctl(g_audio_socket, SNDCTL_DSP_SPEED, &rate); ret = ioctl(g_audio_socket, SNDCTL_DSP_SPEED, &rate);
if(ret < 0) { if(ret < 0) {
printf("ioctl SNDCTL_DSP_SPEED failed, ret:%d, errno:%d\n", printf("ioctl SNDCTL_DSP_SPEED failed, ret:%d, errno:%d\n",
ret, errno); ret, errno);
exit(1); exit(1);
} }
if(ret > 0) { if(ret > 0) {
rate = ret; /* rate is returned value */ rate = ret; /* rate is returned value */
} }
if(rate < 8000) { if(rate < 8000) {
printf("Audio rate of %d which is < 8000!\n", rate); printf("Audio rate of %d which is < 8000!\n", rate);
exit(1); exit(1);
} }
g_audio_rate = rate; g_audio_rate = rate;
printf("Sound initialized\n"); printf("Sound initialized\n");
} }
#endif #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 * architecture-dependant stuff
* *
* Written by * Written by
* Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de> * Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>
* *
* This file is part of VICE, the Versatile Commodore Emulator. * This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice. * See README for copyright notice.
* *
@ -24,7 +24,7 @@
* 02111-1307 USA. * 02111-1307 USA.
* *
*/ */
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
@ -33,7 +33,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "../atbridge/pcap_delay.h" #include "../atbridge/pcap_delay.h"
#include "tfesupp.h" #include "tfesupp.h"
#include "../defc.h" #include "../defc.h"
#include "protos_tfe.h" #include "protos_tfe.h"
@ -60,36 +60,35 @@ static char TfePcapErrbuf[PCAP_ERRBUF_SIZE];
#ifdef TFE_DEBUG_PKTDUMP #ifdef TFE_DEBUG_PKTDUMP
static static
void debug_output( const char *text, unsigned char *what, int count ) void debug_output( const char *text, unsigned char *what, int count ) {
{ char buffer[256];
char buffer[256]; char *p = buffer;
char *p = buffer; char *pbuffer1 = what;
char *pbuffer1 = what; int len1 = count;
int len1 = count; int i;
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); OutputDebugString(buffer);
do { } while (len1>0);
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);
} }
#endif // #ifdef TFE_DEBUG_PKTDUMP #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 TfeEnumAdapter is then used to gather information for each adapter present
on the system, where: on the system, where:
ppname points to a pointer which will hold the name of the interface 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 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 For each of these parameters, new memory is allocated, so it has to be
freed with lib_free(). 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. Each function returns 1 on success, and 0 on failure.
TfeEnumAdapter() only fails if there is no more adpater; in this case, TfeEnumAdapter() only fails if there is no more adpater; in this case,
*ppname and *ppdescription are not altered. * ppname and *ppdescription are not altered.
*/ */
int tfe_arch_enumadapter_open(void) int tfe_arch_enumadapter_open(void) {
{ if (pcapdelay_findalldevs(&TfePcapAlldevs, TfePcapErrbuf) == -1)
if (pcapdelay_findalldevs(&TfePcapAlldevs, TfePcapErrbuf) == -1) {
{
#ifdef TFE_DEBUG_ARCH #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 #endif
return 0; return 0;
} }
if (!TfePcapAlldevs) { if (!TfePcapAlldevs) {
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - " log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - "
"Do we have the necessary privilege rights?"); "Do we have the necessary privilege rights?");
#endif #endif
return 0; return 0;
} }
TfePcapNextDev = TfePcapAlldevs; TfePcapNextDev = TfePcapAlldevs;
return 1; return 1;
} }
int tfe_arch_enumadapter(char **ppname, char **ppdescription) int tfe_arch_enumadapter(char **ppname, char **ppdescription) {
{ if (!TfePcapNextDev || (TfePcapNextDev->name == NULL))
if (!TfePcapNextDev || (TfePcapNextDev->name == NULL)) return 0;
return 0;
*ppname = lib_stralloc(TfePcapNextDev->name); *ppname = lib_stralloc(TfePcapNextDev->name);
if (TfePcapNextDev->description) if (TfePcapNextDev->description)
*ppdescription = lib_stralloc(TfePcapNextDev->description); *ppdescription = lib_stralloc(TfePcapNextDev->description);
else else
*ppdescription = lib_stralloc(TfePcapNextDev->name); *ppdescription = lib_stralloc(TfePcapNextDev->name);
TfePcapNextDev = TfePcapNextDev->next; TfePcapNextDev = TfePcapNextDev->next;
return 1; return 1;
} }
int tfe_arch_enumadapter_close(void) int tfe_arch_enumadapter_close(void) {
{ if (TfePcapAlldevs) {
if (TfePcapAlldevs) { pcapdelay_freealldevs(TfePcapAlldevs);
pcapdelay_freealldevs(TfePcapAlldevs); TfePcapAlldevs = NULL;
TfePcapAlldevs = NULL; }
} return 1;
return 1;
} }
static static
int TfePcapOpenAdapter(const char *interface_name) int TfePcapOpenAdapter(const char *interface_name) {
{ pcap_if_t *TfePcapDevice = NULL;
pcap_if_t *TfePcapDevice = NULL;
if (!tfe_enumadapter_open()) { if (!tfe_enumadapter_open()) {
return FALSE; return FALSE;
} }
else { else {
/* look if we can find the specified adapter */ /* look if we can find the specified adapter */
char *pname; char *pname;
char *pdescription; char *pdescription;
int found = FALSE; int found = FALSE;
if (interface_name) { if (interface_name) {
/* we have an interface name, try it */ /* we have an interface name, try it */
TfePcapDevice = TfePcapAlldevs; TfePcapDevice = TfePcapAlldevs;
while (tfe_enumadapter(&pname, &pdescription)) { while (tfe_enumadapter(&pname, &pdescription)) {
if (strcmp(pname, interface_name)==0) { if (strcmp(pname, interface_name)==0) {
found = TRUE; found = TRUE;
}
lib_free(pname);
lib_free(pdescription);
if (found) break;
TfePcapDevice = TfePcapNextDev;
}
}
if (!found) {
/* just take the first adapter */
TfePcapDevice = TfePcapAlldevs;
} }
lib_free(pname);
lib_free(pdescription);
if (found) break;
TfePcapDevice = TfePcapNextDev;
}
} }
TfePcapFP = pcapdelay_open_live(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf); if (!found) {
if ( TfePcapFP == NULL) /* just take the first adapter */
{ TfePcapDevice = TfePcapAlldevs;
#ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "ERROR opening adapter: '%s'", TfePcapErrbuf);
#endif
tfe_enumadapter_close();
return FALSE;
} }
}
if (pcapdelay_setnonblock(TfePcapFP, 1, TfePcapErrbuf)<0) TfePcapFP = pcapdelay_open_live(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf);
{ if ( TfePcapFP == NULL)
{
#ifdef TFE_DEBUG_ARCH #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 #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(); 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 */ /* the architecture-dependend functions */
int tfe_arch_init(void) int tfe_arch_init(void) {
{ //tfe_arch_log = log_open("TFEARCH");
//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 #ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_pre_reset()." ); log_message( tfe_arch_log, "tfe_arch_pre_reset()." );
#endif #endif
} }
void tfe_arch_post_reset( void ) void tfe_arch_post_reset( void ) {
{
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_post_reset()." ); log_message( tfe_arch_log, "tfe_arch_post_reset()." );
#endif #endif
} }
int tfe_arch_activate(const char *interface_name) int tfe_arch_activate(const char *interface_name) {
{
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_activate()." ); log_message( tfe_arch_log, "tfe_arch_activate()." );
#endif #endif
if (!TfePcapOpenAdapter(interface_name)) { if (!TfePcapOpenAdapter(interface_name)) {
return 0; return 0;
} }
return 1; return 1;
} }
void tfe_arch_deactivate( void ) void tfe_arch_deactivate( void ) {
{
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_deactivate()." ); log_message( tfe_arch_log, "tfe_arch_deactivate()." );
#endif #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) #if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
log_message( tfe_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", 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] ); mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
#endif #endif
} }
@ -275,49 +264,46 @@ void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */
int bCorrect, /* accept correct frames */ int bCorrect, /* accept correct frames */
int bPromiscuous, /* promiscuous mode */ int bPromiscuous, /* promiscuous mode */
int bIAHash /* accept if IA passes the hash filter */ int bIAHash /* accept if IA passes the hash filter */
) ) {
{
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) #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, "tfe_arch_recv_ctl() called with the following parameters:" );
log_message( tfe_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" ); 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, "\tbIA = %s", bIA ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbMulticast = %s", bMulticast ? "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, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "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, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" );
#endif #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) #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, "tfe_arch_line_ctl() called with the following parameters:" );
log_message( tfe_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" ); 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, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" );
#endif #endif
} }
typedef struct TFE_PCAP_INTERNAL_tag { typedef struct TFE_PCAP_INTERNAL_tag {
unsigned int len; unsigned int len;
unsigned char *buffer; unsigned char *buffer;
} TFE_PCAP_INTERNAL; } TFE_PCAP_INTERNAL;
/* Callback function invoked by libpcap for every incoming packet */ /* Callback function invoked by libpcap for every incoming packet */
static static
void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data) void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data) {
{ TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL*)param;
TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL*)param;
/* determine the count of bytes which has been returned, /* determine the count of bytes which has been returned,
* but make sure not to overrun the buffer * but make sure not to overrun the buffer
*/ */
if (header->caplen < pinternal->len) if (header->caplen < pinternal->len)
pinternal->len = header->caplen; pinternal->len = header->caplen;
memcpy(pinternal->buffer, pkt_data, pinternal->len); memcpy(pinternal->buffer, pkt_data, pinternal->len);
} }
/* the following function receives a frame. /* 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's none, it returns a -1.
If there is one, it returns the length of the frame in bytes. 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. bytes as return value.
At most 'len' bytes are copied. At most 'len' bytes are copied.
*/ */
static static
int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) {
{ int ret = -1;
int ret = -1;
/* check if there is something to receive */ /* check if there is something to receive */
if (pcapdelay_dispatch(TfePcapFP, 1, (pcap_handler)TfePcapPacketHandler, (unsigned char*)pinternal)!=0) { if (pcapdelay_dispatch(TfePcapFP, 1, (pcap_handler)TfePcapPacketHandler, (unsigned char*)pinternal)!=0) {
/* Something has been received */ /* Something has been received */
ret = pinternal->len; ret = pinternal->len;
} }
#ifdef TFE_DEBUG_ARCH #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 #endif
return ret; return ret;
} }
void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ 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 tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
int txlength, /* Frame length */ int txlength, /* Frame length */
unsigned char *txframe /* Pointer to the frame to be transmitted */ unsigned char *txframe /* Pointer to the frame to be transmitted */
) ) {
{
#ifdef TFE_DEBUG_ARCH #ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_transmit() called, with: " log_message( tfe_arch_log, "tfe_arch_transmit() called, with: "
"force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u", "force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
force ? "TRUE" : "FALSE", force ? "TRUE" : "FALSE",
onecoll ? "TRUE" : "FALSE", onecoll ? "TRUE" : "FALSE",
inhibit_crc ? "TRUE" : "FALSE", inhibit_crc ? "TRUE" : "FALSE",
tx_pad_dis ? "TRUE" : "FALSE", tx_pad_dis ? "TRUE" : "FALSE",
txlength txlength
); );
#endif #endif
#ifdef TFE_DEBUG_PKTDUMP #ifdef TFE_DEBUG_PKTDUMP
debug_output( "Transmit frame: ", txframe, txlength); debug_output( "Transmit frame: ", txframe, txlength);
#endif // #ifdef TFE_DEBUG_PKTDUMP #endif // #ifdef TFE_DEBUG_PKTDUMP
if (pcapdelay_sendpacket(TfePcapFP, txframe, txlength) == -1) { if (pcapdelay_sendpacket(TfePcapFP, txframe, txlength) == -1) {
//log_message(tfe_arch_log, "WARNING! Could not send packet!"); //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. This function checks if there was a frame received.
If so, it returns 1, else 0. 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 - 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 - *plen gets the length of the received frame, EVEN if this is more
than has been copied to pbuffer! 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. 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 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. 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. (set by tfe_arch_set_mac()), *pcorrect_mac is set, else cleared.
- if the dest. address was accepted since it was a broadcast address, - if the dest. address was accepted since it was a broadcast address,
*pbroadcast is set, else cleared. * pbroadcast is set, else cleared.
- if the received frame had a crc error, *pcrc_error 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 tfe_arch_receive(unsigned char *pbuffer, /* where to store a frame */
int *plen, /* IN: maximum length of frame to copy; int *plen, /* IN: maximum length of frame to copy;
OUT: length of received frame OUT: length of received frame
OUT can be bigger than IN if received frame was OUT can be bigger than IN if received frame was
longer than supplied buffer */ longer than supplied buffer */
int *phashed, /* set if the dest. address is accepted by the hash filter */ 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 *prx_ok, /* set if good CRC and valid length */
int *pcorrect_mac, /* set if dest. address is exactly our IA */ int *pcorrect_mac, /* set if dest. address is exactly our IA */
int *pbroadcast, /* set if dest. address is a broadcast address */ int *pbroadcast, /* set if dest. address is a broadcast address */
int *pcrc_error /* set if received frame had a CRC error */ 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 #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 #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 #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 #endif // #ifdef TFE_DEBUG_PKTDUMP
if (len&1) if (len&1)
++len; ++len;
*plen = len; *plen = len;
/* we don't decide if this frame fits the needs; /* we don't decide if this frame fits the needs;
* by setting all zero, we let tfe.c do the work * by setting all zero, we let tfe.c do the work
* for us * for us
*/ */
*phashed = *phashed =
*phash_index = *phash_index =
*pbroadcast = *pbroadcast =
*pcorrect_mac = *pcorrect_mac =
*pcrc_error = 0; *pcrc_error = 0;
/* this frame has been received correctly */ /* this frame has been received correctly */
*prx_ok = 1; *prx_ok = 1;
return 1; return 1;
} }
return 0; return 0;
} }

View File

@ -61,123 +61,117 @@
static unsigned long crc32_table[256]; static unsigned long crc32_table[256];
static int crc32_is_initialized = 0; static int crc32_is_initialized = 0;
void lib_free(void *ptr) void lib_free(void *ptr) {
{
#ifdef LIB_DEBUG #ifdef LIB_DEBUG
lib_debug_free(ptr, 1, 1); lib_debug_free(ptr, 1, 1);
#endif #endif
#ifdef LIB_DEBUG #ifdef LIB_DEBUG
lib_debug_libc_free(ptr); lib_debug_libc_free(ptr);
#else #else
free(ptr); free(ptr);
#endif #endif
} }
void *lib_malloc(size_t size) void *lib_malloc(size_t size) {
{
#ifdef LIB_DEBUG #ifdef LIB_DEBUG
void *ptr = lib_debug_libc_malloc(size); void *ptr = lib_debug_libc_malloc(size);
#else #else
void *ptr = malloc(size); void *ptr = malloc(size);
#endif #endif
if (ptr == NULL && size > 0) if (ptr == NULL && size > 0)
exit(-1); exit(-1);
#ifdef LIB_DEBUG #ifdef LIB_DEBUG
lib_debug_alloc(ptr, size, 3); lib_debug_alloc(ptr, size, 3);
#endif #endif
return ptr; return ptr;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Malloc enough space for `str', copy `str' into it and return its /* Malloc enough space for `str', copy `str' into it and return its
address. */ address. */
char *lib_stralloc(const char *str) char *lib_stralloc(const char *str) {
{ size_t size;
size_t size; char *ptr;
char *ptr;
if (str == NULL) if (str == NULL)
exit(-1); exit(-1);
size = strlen(str) + 1; size = strlen(str) + 1;
ptr = (char *)lib_malloc(size); ptr = (char *)lib_malloc(size);
memcpy(ptr, str, size); memcpy(ptr, str, size);
return ptr; return ptr;
} }
/* Like realloc, but abort if not enough memory is available. */ /* 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 #ifdef LIB_DEBUG
void *new_ptr = lib_debug_libc_realloc(ptr, size); void *new_ptr = lib_debug_libc_realloc(ptr, size);
#else #else
void *new_ptr = realloc(ptr, size); void *new_ptr = realloc(ptr, size);
#endif #endif
if (new_ptr == NULL) if (new_ptr == NULL)
exit(-1); exit(-1);
#ifdef LIB_DEBUG #ifdef LIB_DEBUG
lib_debug_free(ptr, 1, 0); lib_debug_free(ptr, 1, 0);
lib_debug_alloc(new_ptr, size, 1); lib_debug_alloc(new_ptr, size, 1);
#endif #endif
return new_ptr; return new_ptr;
} }
// Util Stuff // Util Stuff
/* Set a new value to the dynamically allocated string *str. /* Set a new value to the dynamically allocated string *str.
Returns `-1' if nothing has to be done. */ Returns `-1' if nothing has to be done. */
int util_string_set(char **str, const char *new_value) int util_string_set(char **str, const char *new_value) {
{ if (*str == NULL) {
if (*str == NULL) { if (new_value != NULL)
if (new_value != NULL) *str = lib_stralloc(new_value);
*str = lib_stralloc(new_value); } else {
if (new_value == NULL) {
lib_free(*str);
*str = NULL;
} else { } else {
if (new_value == NULL) { /* Skip copy if src and dest are already the same. */
lib_free(*str); if (strcmp(*str, new_value) == 0)
*str = NULL; return -1;
} else {
/* 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); *str = (char *)lib_realloc(*str, strlen(new_value) + 1);
strcpy(*str, new_value); strcpy(*str, new_value);
}
} }
return 0; }
return 0;
} }
// crc32 Stuff // crc32 Stuff
unsigned long crc32_buf(const char *buffer, unsigned int len) unsigned long crc32_buf(const char *buffer, unsigned int len) {
{ int i, j;
int i, j; unsigned long crc, c;
unsigned long crc, c; const char *p;
const char *p;
if (!crc32_is_initialized) { if (!crc32_is_initialized) {
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
c = (unsigned long) i; c = (unsigned long) i;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1; c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1;
crc32_table[i] = c; crc32_table[i] = c;
}
crc32_is_initialized = 1;
} }
crc32_is_initialized = 1;
}
crc = 0xffffffff; crc = 0xffffffff;
for (p = buffer; len > 0; ++p, --len) for (p = buffer; len > 0; ++p, --len)
crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff]; 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 GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#include "defc.h" #include "defc.h"
#include "sound.h" #include "sound.h"
@ -18,215 +18,201 @@ extern int g_audio_rate;
unsigned int __stdcall child_sound_loop_win32(void *param); unsigned int __stdcall child_sound_loop_win32(void *param);
void check_wave_error(int res, char *str); 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]; WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
extern int g_audio_enable; extern int g_audio_enable;
extern word32 *g_sound_shm_addr; extern word32 *g_sound_shm_addr;
extern int g_preferred_rate; extern int g_preferred_rate;
int g_win32snd_buflen = 0x1000; int g_win32snd_buflen = 0x1000;
void void win32snd_init(word32 *shmaddr) {
win32snd_init(word32 *shmaddr) printf("win32snd_init\n");
{ child_sound_loop(-1, -1, shmaddr);
printf("win32snd_init\n");
child_sound_loop(-1, -1, shmaddr);
return; return;
} }
// OG Added global to free the dedicated win32 sound memory // OG Added global to free the dedicated win32 sound memory
byte *bptr = NULL; byte *bptr = NULL;
// OG shut win32 sound resources // OG shut win32 sound resources
void void win32snd_shutdown() {
win32snd_shutdown()
{
if (g_wave_handle) if (g_wave_handle)
{ {
MMRESULT res = waveOutReset(g_wave_handle); MMRESULT res = waveOutReset(g_wave_handle);
if (res!=MMSYSERR_NOERROR ) if (res!=MMSYSERR_NOERROR )
printf("waveOutReset Failed"); printf("waveOutReset Failed");
res = waveOutClose(g_wave_handle); res = waveOutClose(g_wave_handle);
if (res!=MMSYSERR_NOERROR ) if (res!=MMSYSERR_NOERROR )
printf("waveOutClose Failed"); printf("waveOutClose Failed");
g_wave_handle=NULL; g_wave_handle=NULL;
} }
// OG Free dedicated sound memory // OG Free dedicated sound memory
if (bptr) if (bptr)
{ {
free(bptr); free(bptr);
bptr = NULL; bptr = NULL;
} }
} }
void CALLBACK void CALLBACK handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
DWORD_PTR dwParam2) LPWAVEHDR lpwavehdr;
{
LPWAVEHDR lpwavehdr;
/* Only service "buffer done playing messages */ /* Only service "buffer done playing messages */
if(uMsg == WOM_DONE) { if(uMsg == WOM_DONE) {
lpwavehdr = (LPWAVEHDR)dwParam1; lpwavehdr = (LPWAVEHDR)dwParam1;
if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) { if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) {
lpwavehdr->dwUser = FALSE; lpwavehdr->dwUser = FALSE;
} }
} }
return; return;
} }
void void check_wave_error(int res, char *str) {
check_wave_error(int res, char *str) TCHAR buf[256];
{
TCHAR buf[256];
if(res == MMSYSERR_NOERROR) { if(res == MMSYSERR_NOERROR) {
return; return;
} }
waveOutGetErrorText(res, &buf[0], sizeof(buf)); waveOutGetErrorText(res, &buf[0], sizeof(buf));
printf("%s: %s\n", str, buf); printf("%s: %s\n", str, buf);
exit(1); exit(1);
} }
void void child_sound_init_win32() {
child_sound_init_win32() WAVEFORMATEX wavefmt;
{ WAVEOUTCAPS caps;
WAVEFORMATEX wavefmt;
WAVEOUTCAPS caps;
// OG Moved as global variable (to rename) // OG Moved as global variable (to rename)
// byte *bptr; // byte *bptr;
int bits_per_sample, channels, block_align; int bits_per_sample, channels, block_align;
int blen; int blen;
int res; int res;
int i; 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 #ifndef UNDER_CE
bits_per_sample = 16; bits_per_sample = 16;
wavefmt.nSamplesPerSec = g_audio_rate; wavefmt.nSamplesPerSec = g_audio_rate;
#else #else
bits_per_sample = 16; bits_per_sample = 16;
wavefmt.nSamplesPerSec = 12000; wavefmt.nSamplesPerSec = 12000;
#endif #endif
channels = 2; channels = 2;
wavefmt.wBitsPerSample = bits_per_sample; wavefmt.wBitsPerSample = bits_per_sample;
wavefmt.nChannels = channels; wavefmt.nChannels = channels;
block_align = channels * (bits_per_sample / 8); block_align = channels * (bits_per_sample / 8);
wavefmt.nBlockAlign = block_align; wavefmt.nBlockAlign = block_align;
wavefmt.nAvgBytesPerSec = block_align * g_audio_rate; wavefmt.nAvgBytesPerSec = block_align * g_audio_rate;
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0, res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0,
WAVE_FORMAT_QUERY); WAVE_FORMAT_QUERY);
if(res != MMSYSERR_NOERROR) { if(res != MMSYSERR_NOERROR) {
printf("Cannot open audio device\n"); printf("Cannot open audio device\n");
g_audio_enable = 0; g_audio_enable = 0;
return; return;
} }
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt,
(DWORD_PTR)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC); (DWORD_PTR)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
if(res != MMSYSERR_NOERROR) { if(res != MMSYSERR_NOERROR) {
printf("Cannot register audio\n"); printf("Cannot register audio\n");
g_audio_enable = 0; g_audio_enable = 0;
return; return;
} }
g_audio_rate = wavefmt.nSamplesPerSec; g_audio_rate = wavefmt.nSamplesPerSec;
blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS; blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS;
g_win32snd_buflen = blen; g_win32snd_buflen = blen;
bptr = (byte*)malloc(blen * NUM_WAVE_HEADERS); // OG Added cast bptr = (byte*)malloc(blen * NUM_WAVE_HEADERS); // OG Added cast
if(bptr == NULL) { if(bptr == NULL) {
printf("Unabled to allocate sound buffer\n"); printf("Unabled to allocate sound buffer\n");
exit(1); exit(1);
} }
for(i = 0; i < NUM_WAVE_HEADERS; i++) { for(i = 0; i < NUM_WAVE_HEADERS; i++) {
memset(&g_wavehdr[i], 0, sizeof(WAVEHDR)); memset(&g_wavehdr[i], 0, sizeof(WAVEHDR));
g_wavehdr[i].dwUser = FALSE; g_wavehdr[i].dwUser = FALSE;
g_wavehdr[i].lpData = (LPSTR)&(bptr[i*blen]); // OG Added cast g_wavehdr[i].lpData = (LPSTR)&(bptr[i*blen]); // OG Added cast
g_wavehdr[i].dwBufferLength = blen; g_wavehdr[i].dwBufferLength = blen;
g_wavehdr[i].dwFlags = 0; g_wavehdr[i].dwFlags = 0;
g_wavehdr[i].dwLoops = 0; g_wavehdr[i].dwLoops = 0;
res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i], res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i],
sizeof(WAVEHDR)); sizeof(WAVEHDR));
check_wave_error(res, "waveOutPrepareHeader"); check_wave_error(res, "waveOutPrepareHeader");
} }
res = waveOutGetDevCaps((UINT_PTR)g_wave_handle, &caps, sizeof(caps)); res = waveOutGetDevCaps((UINT_PTR)g_wave_handle, &caps, sizeof(caps));
check_wave_error(res, "waveOutGetDevCaps"); check_wave_error(res, "waveOutGetDevCaps");
printf("Using %s\n", caps.szPname); printf("Using %s\n", caps.szPname);
printf(" Bits per Sample = %d. Channels = %d\n", printf(" Bits per Sample = %d. Channels = %d\n",
wavefmt.wBitsPerSample, wavefmt.nChannels); wavefmt.wBitsPerSample, wavefmt.nChannels);
printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n", printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n",
(int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec); (int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec);
set_audio_rate(g_audio_rate); set_audio_rate(g_audio_rate);
} }
void void win32_send_audio2(byte *ptr, int size) {
win32_send_audio2(byte *ptr, int size) int found;
{ int res;
int found; int i;
int res;
int i;
found = 0; found = 0;
for(i = 0; i < NUM_WAVE_HEADERS; i++) { for(i = 0; i < NUM_WAVE_HEADERS; i++) {
if(g_wavehdr[i].dwUser == FALSE) { if(g_wavehdr[i].dwUser == FALSE) {
found = 1; found = 1;
break; break;
} }
} }
if(!found) { if(!found) {
/* all audio buffers busy, just get out */ /* all audio buffers busy, just get out */
return; return;
} }
memcpy(g_wavehdr[i].lpData, ptr, size); memcpy(g_wavehdr[i].lpData, ptr, size);
g_wavehdr[i].dwBufferLength = size; g_wavehdr[i].dwBufferLength = size;
g_wavehdr[i].dwUser = TRUE; g_wavehdr[i].dwUser = TRUE;
res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr)); res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr));
check_wave_error(res, "waveOutWrite"); check_wave_error(res, "waveOutWrite");
return; return;
} }
int int win32_send_audio(byte *ptr, int in_size) {
win32_send_audio(byte *ptr, int in_size) int size;
{ int tmpsize;
int size;
int tmpsize;
size = in_size; size = in_size;
while(size > 0) { while(size > 0) {
tmpsize = size; tmpsize = size;
if(size > g_win32snd_buflen) { if(size > g_win32snd_buflen) {
tmpsize = g_win32snd_buflen; tmpsize = g_win32snd_buflen;
} }
win32_send_audio2(ptr, tmpsize); win32_send_audio2(ptr, tmpsize);
ptr += tmpsize; ptr += tmpsize;
size = size - tmpsize; size = size - tmpsize;
} }
return in_size; return in_size;
} }

View File

@ -1,12 +1,12 @@
/* /*
GSPLUS - Advanced Apple IIGS Emulator Environment GSPLUS - Advanced Apple IIGS Emulator Environment
Based on the KEGS emulator written by Kent Dickey Based on the KEGS emulator written by Kent Dickey
See COPYRIGHT.txt for Copyright information See COPYRIGHT.txt for Copyright information
See LICENSE.txt for license (GPL v2) See LICENSE.txt for license (GPL v2)
*/ */
#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */ #define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */
#define STRICT /* Tell Windows we want compile type checks */ #define STRICT /* Tell Windows we want compile type checks */
#include <windows.h> #include <windows.h>
#include <Shlwapi.h> #include <Shlwapi.h>
@ -21,206 +21,188 @@ extern void gsportshut();
extern HWND g_hwnd_main; extern HWND g_hwnd_main;
extern char *g_status_ptrs[MAX_STATUS_LINES]; extern char *g_status_ptrs[MAX_STATUS_LINES];
extern int g_win_status_debug; extern int g_win_status_debug;
extern int g_win_status_debug_request; extern int g_win_status_debug_request;
extern int g_win_fullscreen_state; extern int g_win_fullscreen_state;
int int win_nonblock_read_stdin(int fd, char *bufptr, int len) {
win_nonblock_read_stdin(int fd, char *bufptr, int len) DWORD charsRead = 0;
{ ReadConsole(GetStdHandle(STD_INPUT_HANDLE), bufptr, len, &charsRead, NULL);
DWORD charsRead = 0;
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), bufptr, len, &charsRead, NULL); if (charsRead == 0)
{
if (charsRead == 0) errno = EAGAIN;
{ return -1;
errno = EAGAIN; }
return -1; else
} {
else DWORD charsWritten = 0;
{ WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), bufptr, charsRead, &charsWritten, NULL);
DWORD charsWritten = 0; return charsRead;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), bufptr, charsRead, &charsWritten, NULL); }
return charsRead;
}
} }
void get_cwd(LPTSTR buffer, int size) void get_cwd(LPTSTR buffer, int size) {
{ HMODULE hSelf;
HMODULE hSelf; hSelf = GetModuleHandle(NULL);
hSelf = GetModuleHandle(NULL); GetModuleFileName(hSelf,buffer,size);
GetModuleFileName(hSelf,buffer,size); PathRemoveFileSpec(buffer);
PathRemoveFileSpec(buffer); //printf("Local directory: [%s]\n",buffer);
//printf("Local directory: [%s]\n",buffer);
} }
void void x_dialog_create_gsport_conf(const char *str) {
x_dialog_create_gsport_conf(const char *str) // Just write the config file already...
{ config_write_config_gsplus_file();
// Just write the config file already...
config_write_config_gsplus_file();
} }
int int x_show_alert(int is_fatal, const char *str) {
x_show_alert(int is_fatal, const char *str) return 0;
{
return 0;
} }
void get_default_window_size(LPSIZE size) void get_default_window_size(LPSIZE size) {
{ // Calculate the window client dimensions.
// Calculate the window client dimensions. RECT rect;
RECT rect; rect.left = 0;
rect.left = 0; rect.top = 0;
rect.top = 0; rect.bottom = X_A2_WINDOW_HEIGHT;
rect.bottom = X_A2_WINDOW_HEIGHT; if (g_win_status_debug)
if (g_win_status_debug) rect.bottom += (MAX_STATUS_LINES * 16);
rect.bottom += (MAX_STATUS_LINES * 16); rect.right = X_A2_WINDOW_WIDTH;
rect.right = X_A2_WINDOW_WIDTH;
// Calculate the window rectangle, which is the client area plus non-client area (e.g. frame and caption). // 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); AdjustWindowRect(&rect, WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
// Return the window size. // Return the window size.
size->cx = rect.right - rect.left; size->cx = rect.right - rect.left;
size->cy = rect.bottom - rect.top; size->cy = rect.bottom - rect.top;
} }
void x_toggle_status_lines() void x_toggle_status_lines() {
{ SIZE size;
SIZE size;
if (!g_win_fullscreen_state) if (!g_win_fullscreen_state)
{ {
g_win_status_debug = !g_win_status_debug; g_win_status_debug = !g_win_status_debug;
g_win_status_debug_request = g_win_status_debug; g_win_status_debug_request = g_win_status_debug;
get_default_window_size(&size); get_default_window_size(&size);
SetWindowPos(g_hwnd_main, NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(g_hwnd_main, NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOZORDER);
x_redraw_status_lines(); x_redraw_status_lines();
} }
} }
void x_show_console(int show) void x_show_console(int show) {
{ HWND hWnd = GetConsoleWindow();
HWND hWnd = GetConsoleWindow(); if (hWnd)
if (hWnd) ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
if (g_hwnd_main) if (g_hwnd_main)
SetFocus(g_hwnd_main); SetFocus(g_hwnd_main);
} }
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
{ return main(0,0);
return main(0,0);
} }
int int main(int argc, char **argv) {
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);
// Hide the console initially to reduce window flashing. We'll show the console later if needed.
x_show_console(0);
// Register the window class. // Register the window class.
WNDCLASS wndclass; WNDCLASS wndclass;
SIZE size; SIZE size;
RECT rect; RECT rect;
wndclass.style = 0; wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)win_event_handler; wndclass.lpfnWndProc = (WNDPROC)win_event_handler;
wndclass.cbClsExtra = 0; wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0; wndclass.cbWndExtra = 0;
wndclass.hInstance = GetModuleHandle(NULL); wndclass.hInstance = GetModuleHandle(NULL);
wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDC_GSPORT32)); wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDC_GSPORT32));
wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName = NULL; wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "gsport"; wndclass.lpszClassName = "gsport";
if(!RegisterClass(&wndclass)) { if(!RegisterClass(&wndclass)) {
printf("Registering window failed\n"); printf("Registering window failed\n");
exit(1); exit(1);
} }
// Create the window. // Create the window.
get_default_window_size(&size); get_default_window_size(&size);
HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, "gsport", "GSplus - Apple //gs Emulator", HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, "gsport", "GSplus - Apple //gs Emulator",
WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
size.cx, size.cy, size.cx, size.cy,
NULL, NULL, GetModuleHandle(NULL), NULL); NULL, NULL, GetModuleHandle(NULL), NULL);
printf("g_hwnd_main = %p, height = %d\n", hwnd, size.cx); printf("g_hwnd_main = %p, height = %d\n", hwnd, size.cx);
GetWindowRect(hwnd, &rect); GetWindowRect(hwnd, &rect);
printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top, printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top,
rect.right, rect.bottom); rect.right, rect.bottom);
// Enable non-blocking, character-at-a-time console I/O. // Enable non-blocking, character-at-a-time console I/O.
// win_nonblock_read_stdin() expects this behavior. // win_nonblock_read_stdin() expects this behavior.
DWORD mode; DWORD mode;
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode); GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
mode &= ~ENABLE_LINE_INPUT; mode &= ~ENABLE_LINE_INPUT;
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode); SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
gsportinit(hwnd); gsportinit(hwnd);
int ret = gsplusmain(argc, argv); int ret = gsplusmain(argc, argv);
UnregisterClass(wndclass.lpszClassName,GetModuleHandle(NULL));
gsportshut(); UnregisterClass(wndclass.lpszClassName,GetModuleHandle(NULL));
return ret;
gsportshut();
return ret;
} }
void x_check_input_events() void x_check_input_events() {
{ MSG msg;
MSG msg;
while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) { while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) {
if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) { if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} else { } else {
printf("GetMessage returned <= 0\n"); printf("GetMessage returned <= 0\n");
my_exit(2); my_exit(2);
} }
} }
} }
void void x_redraw_status_lines() {
x_redraw_status_lines() COLORREF oldtextcolor, oldbkcolor;
{ char *buf;
COLORREF oldtextcolor, oldbkcolor; int line;
char *buf; int len;
int line; int height;
int len; int margin;
int height;
int margin;
height = 16; height = 16;
margin = 0; margin = 0;
if (g_win_status_debug) if (g_win_status_debug)
{ {
HDC localdc = GetDC(g_hwnd_main); HDC localdc = GetDC(g_hwnd_main);
oldtextcolor = SetTextColor(localdc, RGB(255, 255, 255)); oldtextcolor = SetTextColor(localdc, RGB(255, 255, 255));
oldbkcolor = SetBkColor(localdc, RGB(0, 0, 0)); oldbkcolor = SetBkColor(localdc, RGB(0, 0, 0));
for(line = 0; line < MAX_STATUS_LINES; line++) { for(line = 0; line < MAX_STATUS_LINES; line++) {
buf = g_status_ptrs[line]; buf = g_status_ptrs[line];
if(buf != 0) { if(buf != 0) {
len = strlen(buf); len = strlen(buf);
TextOut(localdc, 10, X_A2_WINDOW_HEIGHT + TextOut(localdc, 10, X_A2_WINDOW_HEIGHT +
height*line + margin, buf, len); height*line + margin, buf, len);
} }
} }
SetTextColor(localdc, oldtextcolor); SetTextColor(localdc, oldtextcolor);
SetBkColor(localdc, oldbkcolor); SetBkColor(localdc, oldbkcolor);
ReleaseDC(g_hwnd_main,localdc); ReleaseDC(g_hwnd_main,localdc);
} }
} }
int int x_calc_ratio(float ratiox,float ratioy) {
x_calc_ratio(float ratiox,float ratioy) return 0; // not stretched
{
return 0; // not stretched
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff