static char *dss_fingerprint(void *key) { struct dss_key *dss = (struct dss_key *) key; struct MD5Context md5c; unsigned char digest[16], lenbuf[4]; char buffer[16 * 3 + 40]; size_t pos; int numlen, i; MD5Init(&md5c); MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-dss", 11); #define ADD_BIGNUM(bignum) \ numlen = (bignum_bitcount(bignum)+8)/8; \ PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \ for (i = numlen; i-- ;) { \ unsigned char c = bignum_byte(bignum, i); \ MD5Update(&md5c, &c, 1); \ } ADD_BIGNUM(dss->p); ADD_BIGNUM(dss->q); ADD_BIGNUM(dss->g); ADD_BIGNUM(dss->y); #undef ADD_BIGNUM MD5Final(digest, &md5c); pos = szprintf(buffer, sizeof(buffer), "ssh-dss %d ", bignum_bitcount(dss->p)); for (i = 0; i < 16; i++) pos += szprintf(buffer + pos, sizeof(buffer) - pos, "%s%02x", i ? ":" : "", digest[i]); return dupstr(buffer); }
static char *dss_fmtkey(void *key) { struct dss_key *dss = (struct dss_key *) key; char *p; size_t len, pos; int i, nibbles; static const char hex[] = "0123456789abcdef"; if (!dss->p) return NULL; len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */ len += 4 * (bignum_bitcount(dss->p) + 15) / 16; len += 4 * (bignum_bitcount(dss->q) + 15) / 16; len += 4 * (bignum_bitcount(dss->g) + 15) / 16; len += 4 * (bignum_bitcount(dss->y) + 15) / 16; p = snewn(len, char); if (!p) return NULL; pos = szprintf(p, len, "0x"); nibbles = (3 + bignum_bitcount(dss->p)) / 4; if (nibbles < 1) nibbles = 1; for (i = nibbles; i--;) p[pos++] = hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF]; pos += szprintf(p + pos, len - pos, ",0x"); nibbles = (3 + bignum_bitcount(dss->q)) / 4; if (nibbles < 1) nibbles = 1; for (i = nibbles; i--;) p[pos++] = hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF]; pos += szprintf(p + pos, len - pos, ",0x"); nibbles = (3 + bignum_bitcount(dss->g)) / 4; if (nibbles < 1) nibbles = 1; for (i = nibbles; i--;) p[pos++] = hex[(bignum_byte(dss->g, i / 2) >> (4 * (i % 2))) & 0xF]; pos += szprintf(p + pos, len - pos, ",0x"); nibbles = (3 + bignum_bitcount(dss->y)) / 4; if (nibbles < 1) nibbles = 1; for (i = nibbles; i--;) p[pos++] = hex[(bignum_byte(dss->y, i / 2) >> (4 * (i % 2))) & 0xF]; p[pos] = '\0'; return p; }
int main() { int len; char *message = szprintf(stdlib_memory, &len, "%s:%d", "test", 42); assert(!strcmp(message, "test:42")); assert(len == 7); stdlib_memory.free(message); return 0; }
/** * ScreenShot(): Convenience function to take a screenshot of the game. * @return 0 on success; non-zero on error. */ int ImageUtil::ScreenShot(void) { // If no game is running, don't do anything. if (!Game) return 1; // Variables used: // VDP_Num_Vis_Lines: Number of lines visible on the screen. (bitmap height) // MD_Screen: MD screen buffer. // VDP_Reg.Set4: If 0x01 is set, 320 pixels width; otherwise, 256 pixels width. // TODO: Use macros in video/v_inline.h const int w = (VDP_Reg.Set4 & 0x01 ? 320 : 256); const int h = VDP_Num_Vis_Lines; // Build the filename. int num = -1; char filename[GENS_PATH_MAX]; const char *ext; ImageFormat fmt; #ifdef GENS_PNG if (gsft_png_dll_init() == 0) { // PNG initialized. ext = "png"; fmt = IMAGEFORMAT_PNG; } else #endif /* GENS_PNG */ { // Couldn't initialize PNG. // Use BMP instead. ext = "bmp"; fmt = IMAGEFORMAT_BMP; } do { num++; szprintf(filename, sizeof(filename), "%s%s_%03d.%s", PathNames.Screenshot_Dir, ROM_Filename, num, ext); } while (gsft_file_exists(filename)); void *screen; if (bppMD == 15 || bppMD == 16) screen = (void*)(&MD_Screen[8]); else //if (bppMD == 32) screen = (void*)(&MD_Screen32[8]); // Attempt to save the screenshot. int rval = WriteImage(filename, fmt, w, h, 336, screen, bppMD); if (!rval) vdraw_text_printf(1500, "Screen shot %d saved.", num); return rval; }
/** * gsft_file_rel_to_abs(): Convert a relative pathname to an absolute pathname. * @param path_rel [in] Relative pathname to convert. * @param path_root [in] Root of the relative ptah. * @param path_abs [out] Buffer for the absolute pathname. * @param path_abs_len [in] Length of the absolute pathname buffer. */ void GSFT_FNCALL gsft_file_rel_to_abs(const char *path_rel, const char *path_root, char *path_abs, size_t path_abs_len) { // Check if the relative pathname is actually relative. if (path_rel[0] != '.' || path_rel[1] != GSFT_DIR_SEP_CHR) { // Not relative. Copy the path as-is. strlcpy(path_abs, path_rel, path_abs_len); return; } // Relative pathname. szprintf(path_abs, path_abs_len, "%s%s", path_root, &path_rel[2]); return; }
/** * gsft_file_abs_to_rel(): Convert an absolute pathname to a relative pathname. * @param path_abs [in] Absolute pathname to convert. * @param path_root [in] Root of the relative path. * @param path_rel [out] Buffer for the relative pathname. * @param path_rel_len [in] Length of the relative pathname buffer. */ void GSFT_FNCALL gsft_file_abs_to_rel(const char *path_abs, const char *path_root, char *path_rel, size_t path_rel_len) { // Check if the absolute pathname has the root path in it. const size_t path_root_len = strlen(path_root); if (strncmp(path_abs, path_root, path_root_len) != 0) { // Root path not found. Copy the absolute path as-is. strlcpy(path_rel, path_abs, path_rel_len); return; } // Root path found. szprintf(path_rel, path_rel_len, "." GSFT_DIR_SEP_STR "%s", &path_abs[path_root_len]); return; }
static int MDP_FNCALL ips_event_handler(int event_id, void *event_info) { if (event_id == MDP_EVENT_OPEN_ROM) { mdp_event_open_rom_t *openROM = (mdp_event_open_rom_t*)(event_info); if (!openROM->rom_name) return MDP_ERR_OK; // IPS patch file is [save directory]/ROM_name.ips. char patch_filename[1024]; szprintf(patch_filename, sizeof(patch_filename), "%s/%s.ips", ips_save_path, openROM->rom_name); // Attempt to load the patch. // TODO: Make autoloading based on filename user-configurable. ips_file_load(patch_filename); } // TODO return MDP_ERR_OK; }
/** * wav_dump_start(): Start dumping a WAV file. * @return 0 on success; non-zero on error. */ int wav_dump_start(void) { #ifdef GENS_OS_WIN32 // Make sure relative pathnames are handled correctly on Win32. pSetCurrentDirectoryU(PathNames.Gens_Save_Path); #endif /* A game must be loaded in order to dump a WAV. */ if (!Game) return 0; if (WAV_Dumping) { vdraw_text_write("WAV sound is already dumping.", 1000); return 0; } /* Build the filename. */ char filename[GENS_PATH_MAX]; int num = -1; do { num++; szprintf(filename, sizeof(filename), "%s%s_%03d.wav", PathNames.Dump_WAV_Dir, ROM_Filename, num); } while (!access(filename, F_OK)); /* Open the file. */ WAV_File = fopen(filename, "wb"); if (!WAV_File) { vdraw_text_write("Error opening WAV file.", 1000); return 1; } /* Create the WAV header. */ memset(&WAV_Header, 0x00, sizeof(WAV_Header)); /* "RIFF" header. */ static const char ChunkID_RIFF[4] = {'R', 'I', 'F', 'F'}; static const char FormatID_WAV[4] = {'W', 'A', 'V', 'E'}; memcpy(WAV_Header.riff.ChunkID, ChunkID_RIFF, sizeof(WAV_Header.riff.ChunkID)); memcpy(WAV_Header.riff.Format, FormatID_WAV, sizeof(WAV_Header.riff.Format)); /* "fmt " header. */ static const char SubchunkID_fmt[4] = {'f', 'm', 't', ' '}; memcpy(WAV_Header.fmt.SubchunkID, SubchunkID_fmt, sizeof(WAV_Header.fmt.SubchunkID)); WAV_Header.fmt.SubchunkSize = cpu_to_le32(sizeof(WAV_Header.fmt) - 8); WAV_Header.fmt.AudioFormat = cpu_to_le16(1); /* PCM */ WAV_Header.fmt.NumChannels = cpu_to_le16((audio_get_stereo() ? 2 : 1)); WAV_Header.fmt.SampleRate = cpu_to_le32(audio_get_sound_rate()); WAV_Header.fmt.BitsPerSample = cpu_to_le16(16); /* Gens is currently hard-coded to 16-bit audio. */ /* Calculated fields. */ WAV_Header.fmt.BlockAlign = cpu_to_le16(WAV_Header.fmt.NumChannels * (WAV_Header.fmt.BitsPerSample / 8)); WAV_Header.fmt.ByteRate = cpu_to_le32(WAV_Header.fmt.BlockAlign * WAV_Header.fmt.SampleRate); /* "data" header. */ static const char SubchunkID_data[4] = {'d', 'a', 't', 'a'}; memcpy(WAV_Header.data.SubchunkID, SubchunkID_data, sizeof(WAV_Header.data.SubchunkID)); /* Write the initial header to the file. */ fwrite(&WAV_Header, sizeof(WAV_Header), 1, WAV_File); /* WAV dump started. */ vdraw_text_write("Starting to dump WAV sound.", 1000); WAV_Dumping = 1; Sync_Gens_Window_SoundMenu(); return 0; }
/** * input_get_key_name(): Get a key name. * @param key Key. * @param buf Buffer to store the key name in. ("Unknown Key" is stored on error.) * @param size Size of the buffer. * @return 0 on success; non-zero on error. */ int input_get_key_name(uint16_t key, char* buf, int size) { if (size == 0) return -1; if (key == 0) { // 0 == not configured. strlcpy(buf, "Not Configured", size); return 0; } if (!INPUT_IS_JOYSTICK(key)) { // Not a joystick input. // Defer the key name lookup to the current input handler. if (input_cur_backend) { int rval = input_cur_backend->get_key_name(key, buf, size); if (!rval) return 0; else { // Unknown key. strlcpy(buf, "Unknown Key", size); return rval; } } // No backend available. Return an error. strlcpy(buf, "Unknown Key", size); return -1; } // Joystick input. static const char pov_directions[4][8] = {"Up", "Right", "Down", "Left"}; static const char axis_names[6][4] = {"X", "Y", "Z", "Rx", "Ry", "Rz"}; // Joystick number. const int joy_num = INPUT_JOYSTICK_GET_NUMBER(key); switch (INPUT_JOYSTICK_GET_TYPE(key)) { case INPUT_JOYSTICK_TYPE_AXIS: { int axis = INPUT_JOYSTICK_GET_AXIS(key); char dir = (INPUT_JOYSTICK_GET_AXIS_DIRECTION(key) == INPUT_JOYSTICK_AXIS_NEGATIVE ? '-' : '+'); if (axis < 6) szprintf(buf, size, "Joy %d, Axis %s%c", joy_num, axis_names[axis], dir); else szprintf(buf, size, "Joy %d, Axis %d%c", joy_num, axis, dir); break; } case INPUT_JOYSTICK_TYPE_BUTTON: szprintf(buf, size, "Joy %d, Button %d", joy_num, INPUT_JOYSTICK_GET_BUTTON(key)); break; case INPUT_JOYSTICK_TYPE_POVHAT: szprintf(buf, size, "Joy %d, POV %d %s", joy_num, INPUT_JOYSTICK_GET_POVHAT_NUMBER(key), pov_directions[INPUT_JOYSTICK_GET_POVHAT_DIRECTION(key)]); break; default: strlcpy(buf, "Unknown Joy Key", size); return -1; } return 0; }
/** * z80dis(): Disassemble Z80 code. * @param buf Z80 code to disassemble. * @param Counter ??? * @param str Disassembled Z80 code. * @param size Size of str. * @return ??? */ int z80dis(unsigned char *buf, unsigned int *Counter, char *str, int size) { char S[80], T[80], U[80], *P, *R; int I, J; if ((I = buf[*Counter]) < 0) return (0); memset(S, 0x00, sizeof(S)); memset(T, 0x00, sizeof(T)); memset(U, 0x00, sizeof(U)); memset(str, 0x00, size); szprintf(str, size, "%.4X: %.2X", (*Counter)++, I); switch (I) { case 0xCB: if ((I = buf[*Counter]) < 0) return 0; sprintf(U, "%.2X", I); strcpy(S, MnemonicsCB[I]); (*Counter)++; break; case 0xED: if ((I = buf[*Counter]) < 0) return 0; sprintf(U, "%.2X", I); strcpy(S, MnemonicsED[I]); (*Counter)++; break; case 0xFD: if ((I = buf[*Counter]) < 0) return (0); sprintf (U, "%.2X", I); if (I == 0xCB) { (*Counter)++; if ((I = buf[*Counter]) < 0) return 0; (*Counter)++; if ((J = buf[*Counter]) < 0) return 0; sprintf(U, "%s%.2X%.2X", U, I, J); sprintf(S, "%s, (IY+%.2X)", MnemonicsCB[J], I); } else { strcpy(S, MnemonicsXX[I]); if ((P = strchr(S, '%'))) *P = 'Y'; } (*Counter)++; break; case 0xDD: if ((I = buf[*Counter]) < 0) return 0; sprintf (U, "%.2X", I); if (I == 0xCB) { (*Counter)++; if ((I = buf[*Counter]) < 0) return 0; (*Counter)++; if ((J = buf[*Counter]) < 0) return 0; sprintf(U, "%s%.2X%.2X", U, I, J); sprintf(S, "%s, (IX+%.2X)", MnemonicsCB[J], I); } else { strcpy(S, MnemonicsXX[I]); if ((P = strchr(S, '%'))) *P = 'X'; } (*Counter)++; break; default: strcpy(S, Mnemonics[I]); } if ((P = strchr(S, '*'))) { if ((I = buf[*Counter]) < 0) return 0; sprintf(U, "%s%.2X", U, I); *P++ = '\0'; (*Counter)++; sprintf(T, "%s%hX", S, I); if ((R = strchr(P, '*'))) { if ((I = buf[*Counter]) < 0) return 0; sprintf(U, "%s%.2X", U, I); *R++ = '\0'; (*Counter)++; sprintf(strchr(T, '\0'), "%s%hX%s", P, I, R); } else strcat(T, P); } else if ((P = strchr(S, '#'))) { if ((I = buf[*Counter]) < 0) return 0; (*Counter)++; if ((J = buf[*Counter]) < 0) return 0; sprintf(U, "%s%.2X%.2X", U, I, J); *P++ = '\0'; (*Counter)++; sprintf(T, "%s%hX%s", S, 256 * J + I, P); } else strcpy(T, S); strlcat(str, U, size); if (size >= 19) { // Pad the field to 18 characters. int n; for (n = strlen(str); n <= 17; n++) str[n] = ' '; str[18] = 0x00; } strlcat(str, T, size); strlcat(str, "\n", size); return 1; }
/** * sgens_window_update(): Update the information display. */ void MDP_FNCALL sgens_window_update(void) { if (!sgens_window) return; if (sgens_current_rom_type <= SGENS_ROM_TYPE_UNSUPPORTED) return; // String buffer. char tmp[64]; // Get the widget information. sgens_widget_info info; sgens_get_widget_info(&info); // Values common to all supported Sonic games. // Score. szprintf(tmp, sizeof(tmp), "%d", info.score); Static_SetTextU(lblLevelInfo[LEVEL_INFO_SCORE], tmp); // Time. szprintf(tmp, sizeof(tmp), "%02d:%02d:%02d", info.time.min, info.time.sec, info.time.frames); Static_SetTextU(lblLevelInfo[LEVEL_INFO_TIME], tmp); // Rings. szprintf(tmp, sizeof(tmp), "%d", info.rings); Static_SetTextU(lblLevelInfo[LEVEL_INFO_RINGS], tmp); // Lives. szprintf(tmp, sizeof(tmp), "%d", info.lives); Static_SetTextU(lblLevelInfo[LEVEL_INFO_LIVES], tmp); // Continues. szprintf(tmp, sizeof(tmp), "%d", info.continues); Static_SetTextU(lblLevelInfo[LEVEL_INFO_CONTINUES], tmp); // Rings remaining for Perfect Bonus. // This is only applicable for Sonic 2. if (sgens_current_rom_type >= SGENS_ROM_TYPE_SONIC2_REV00 && sgens_current_rom_type <= SGENS_ROM_TYPE_SONIC2_REV02) { szprintf(tmp, sizeof(tmp), "%d", info.rings_for_perfect_bonus); Static_SetTextU(lblLevelInfo[LEVEL_INFO_RINGS_PERFECT], tmp); } // Water status. szprintf(tmp, sizeof(tmp), "%s", (info.water_level != 0 ? "ON" : "OFF")); Static_SetTextU(lblLevelInfo[LEVEL_INFO_WATER_ENABLED], tmp); // Water level. szprintf(tmp, sizeof(tmp), "%04X", info.water_level); Static_SetTextU(lblLevelInfo[LEVEL_INFO_WATER_LEVEL], tmp); // Number of emeralds. szprintf(tmp, sizeof(tmp), "%d", info.emeralds); Static_SetTextU(lblLevelInfo[LEVEL_INFO_EMERALDS], tmp); // Camera X position. szprintf(tmp, sizeof(tmp), "%04X", info.camera_x); Static_SetTextU(lblLevelInfo[LEVEL_INFO_CAMERA_X], tmp); // Camera Y position. szprintf(tmp, sizeof(tmp), "%04X", info.camera_y); Static_SetTextU(lblLevelInfo[LEVEL_INFO_CAMERA_Y], tmp); // Player angle. szprintf(tmp, sizeof(tmp), "%0.02f" DEGREE_SYMBOL, info.player_angle); Static_SetTextU(lblPlayerInfo[PLAYER_INFO_ANGLE], tmp); // Player X position. szprintf(tmp, sizeof(tmp), "%04X", info.player_x); Static_SetTextU(lblPlayerInfo[PLAYER_INFO_X], tmp); // Player Y position. szprintf(tmp, sizeof(tmp), "%04X", info.player_y); Static_SetTextU(lblPlayerInfo[PLAYER_INFO_Y], tmp); // SGens window has been updated. return; }
/** * ntsc_event_handler(): Event handler function. * @param event_id Event ID. * @param event_info Event information. * @return MDP error code. */ static int MDP_FNCALL ntsc_event_handler(int event_id, void *event_info) { MDP_UNUSED_PARAMETER(event_info); int i, val; char buf[128]; switch (event_id) { case MDP_EVENT_LOAD_CONFIG: // Load NTSC configuration. // Check for presets. ntsc_host_srv->config_get(&mdp, "_Preset", NULL, buf, sizeof(buf)); for (i = 0; i < NTSC_PRESETS_COUNT; i++) { if (!ntsc_presets[i].setup) { // "Custom". This is the last item in the predefined list. // Since the current setup doesn't match anything else, // it must be a custom setup. break; } else { // Check if this preset matches the current setup. if (!strncasecmp(buf, ntsc_presets[i].name, sizeof(buf))) { // Match found! memcpy(&mdp_md_ntsc_setup, ntsc_presets[i].setup, sizeof(mdp_md_ntsc_setup)); break; } } } // If "Custom", load customized values. if (i != NTSC_PRESETS_COUNT) { for (i = 0; i < NTSC_CTRL_COUNT; i++) { ntsc_host_srv->config_get(&mdp, ntsc_controls[i].name, NULL, buf, sizeof(buf)); if (buf[0] == 0x00) { // Empty value. Use "Composite" preset. mdp_md_ntsc_setup.params[i] = md_ntsc_composite.params[i]; } else { // Non-empty value. Convert it to an integer. errno = 0; val = strtol(buf, NULL, 0); if (errno != 0) { // Error occurred while converting the number. // Use the default value. ("Composite" preset.) mdp_md_ntsc_setup.params[i] = md_ntsc_composite.params[i]; } else { // Number converted. // Convert it to an internal NTSC value. mdp_md_ntsc_setup.params[i] = ntsc_display_to_internal(i, val); } } } } // Effects. mdp_md_ntsc_effects = 0; // Scanlines. ntsc_host_srv->config_get(&mdp, "_Scanlines", "1", buf, sizeof(buf)); if (buf[0]) { errno = 0; val = strtol(buf, NULL, 0); if (errno != 0) val = 1; } else val = 1; if (val) mdp_md_ntsc_effects |= MDP_MD_NTSC_EFFECT_SCANLINE; // Interpolation. ntsc_host_srv->config_get(&mdp, "_Interpolation", "1", buf, sizeof(buf)); if (buf[0]) { errno = 0; val = strtol(buf, NULL, 0); if (errno != 0) val = 1; } else val = 1; if (val) mdp_md_ntsc_effects |= MDP_MD_NTSC_EFFECT_INTERP; // Sony CXA2025AS US decoder matrix. ntsc_host_srv->config_get(&mdp, "_Sony_CXA2025AS_US", "0", buf, sizeof(buf)); if (buf[0]) { errno = 0; val = strtol(buf, NULL, 0); if (errno != 0) val = 0; } else val = 0; if (val) mdp_md_ntsc_effects |= MDP_MD_NTSC_EFFECT_CXA2025AS; // Reinitialize the NTSC settings. mdp_md_ntsc_reinit_setup(); ntsc_window_load_settings(); break; case MDP_EVENT_SAVE_CONFIG: // Save NTSC configuration. // Check if the current configuration is a preset. for (i = 0; i < NTSC_PRESETS_COUNT; i++) { if (!ntsc_presets[i].setup) { // "Custom". This is the last item in the predefined list. // Since the current setup doesn't match anything else, // it must be a custom setup. ntsc_host_srv->config_set(&mdp, "_Preset", ntsc_presets[i].name); break; } else { // Check if this preset matches the current setup. if (!memcmp(&mdp_md_ntsc_setup, ntsc_presets[i].setup, sizeof(mdp_md_ntsc_setup))) { // Match found! ntsc_host_srv->config_set(&mdp, "_Preset", ntsc_presets[i].name); break; } } } // Save individual values. for (i = 0; i < NTSC_CTRL_COUNT; i++) { szprintf(buf, sizeof(buf), "%d", ntsc_internal_to_display(i, mdp_md_ntsc_setup.params[i])); ntsc_host_srv->config_set(&mdp, ntsc_controls[i].name, buf); } // Scanlines. buf[1] = 0x00; buf[0] = ((mdp_md_ntsc_effects & MDP_MD_NTSC_EFFECT_SCANLINE) ? '1' : '0'); ntsc_host_srv->config_set(&mdp, "_Scanlines", buf); // Interpolation. buf[0] = ((mdp_md_ntsc_effects & MDP_MD_NTSC_EFFECT_INTERP) ? '1' : '0'); ntsc_host_srv->config_set(&mdp, "_Interpolation", buf); // Sony CXA2025AS US decoder matrix. buf[0] = ((mdp_md_ntsc_effects & MDP_MD_NTSC_EFFECT_CXA2025AS) ? '1' : '0'); ntsc_host_srv->config_set(&mdp, "_Sony_CXA2025AS_US", buf); break; default: // Unhandled event. return -MDP_ERR_EVENT_NOT_REGISTERED; } return MDP_ERR_OK; }
/* * Log an SSH packet. * If n_blanks != 0, blank or omit some parts. * Set of blanking areas must be in increasing order. */ void log_packet(void *handle, int direction, int type, char *texttype, const void *data, int len, int n_blanks, const struct logblank_t *blanks, const unsigned long *seq, unsigned downstream_id, const char *additional_log_text) { struct LogContext *ctx = (struct LogContext *)handle; char dumpdata[80], smalldata[5]; int p = 0, b = 0, omitted = 0; int output_pos = 0; /* NZ if pending output in dumpdata */ if (!(ctx->logtype == LGTYP_SSHRAW || (ctx->logtype == LGTYP_PACKETS && texttype))) return; /* Packet header. */ if (texttype) { logprintf(ctx, "%s packet ", direction == PKT_INCOMING ? "Incoming" : "Outgoing"); if (seq) logprintf(ctx, "#0x%lx, ", *seq); logprintf(ctx, "type %d / 0x%02x (%s)", type, type, texttype); if (downstream_id) { logprintf(ctx, " on behalf of downstream #%u", downstream_id); if (additional_log_text) logprintf(ctx, " (%s)", additional_log_text); } logprintf(ctx, "\r\n"); } else { /* * Raw data is logged with a timestamp, so that it's possible * to determine whether a mysterious delay occurred at the * client or server end. (Timestamping the raw data avoids * cluttering the normal case of only logging decrypted SSH * messages, and also adds conceptual rigour in the case where * an SSH message arrives in several pieces.) */ char buf[256]; struct tm tm; tm = ltime(); strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &tm); logprintf(ctx, "%s raw data at %s\r\n", direction == PKT_INCOMING ? "Incoming" : "Outgoing", buf); } /* * Output a hex/ASCII dump of the packet body, blanking/omitting * parts as specified. */ while (p < len) { int blktype; /* Move to a current entry in the blanking array. */ while ((b < n_blanks) && (p >= blanks[b].offset + blanks[b].len)) b++; /* Work out what type of blanking to apply to * this byte. */ blktype = PKTLOG_EMIT; /* default */ if ((b < n_blanks) && (p >= blanks[b].offset) && (p < blanks[b].offset + blanks[b].len)) blktype = blanks[b].type; /* If we're about to stop omitting, it's time to say how * much we omitted. */ if ((blktype != PKTLOG_OMIT) && omitted) { logprintf(ctx, " (%d byte%s omitted)\r\n", omitted, (omitted==1?"":"s")); omitted = 0; } /* (Re-)initialise dumpdata as necessary * (start of row, or if we've just stopped omitting) */ if (!output_pos && !omitted) szprintf(dumpdata, sizeof(dumpdata), " %08x%*s\r\n", p-(p%16), 1+3*16+2+16, ""); /* Deal with the current byte. */ if (blktype == PKTLOG_OMIT) { omitted++; } else { int c; if (blktype == PKTLOG_BLANK) { c = 'X'; szprintf(smalldata, sizeof(smalldata), "XX"); } else { /* PKTLOG_EMIT */ c = ((unsigned char *)data)[p]; szprintf(smalldata, sizeof(smalldata), "%02x", c); } dumpdata[10+2+3*(p%16)] = smalldata[0]; dumpdata[10+2+3*(p%16)+1] = smalldata[1]; dumpdata[10+1+3*16+2+(p%16)] = (isprint(c) ? c : '.'); output_pos = (p%16) + 1; } p++; /* Flush row if necessary */ if (((p % 16) == 0) || (p == len) || omitted) { if (output_pos) { strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n"); logwrite(ctx, dumpdata, strlen(dumpdata)); output_pos = 0; } } } /* Tidy up */ if (omitted) logprintf(ctx, " (%d byte%s omitted)\r\n", omitted, (omitted==1?"":"s")); logflush(ctx); }
/** * vdpdbg_window_update_lstRegList(): Update the VDP register list. * @param reg_vdp VDP registers. */ static void vdpdbg_window_update_lstRegList(mdp_reg_vdp_t *reg_vdp) { // Go through the list and update the registers. // TODO: If a user is editing a register, don't update that register. GtkTreeIter iter; int reg_num; char hex_value[16]; char desc[1024]; uint8_t reg_value; int prev_value; // DMA Length and DMA Src Addr stuff. GtkTreeIter iter_DMA_Len; GtkTreeIter iter_DMA_Src; gboolean DMA_Len_NeedsUpdate = FALSE; gboolean DMA_Src_NeedsUpdate = FALSE; gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(lmRegList), &iter); while (valid) { gtk_tree_model_get(GTK_TREE_MODEL(lmRegList), &iter, 0, ®_num, 2, &prev_value, -1); if (reg_num < 0 || reg_num >= 24) { // Invalid register number. Go to the next entry. valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(lmRegList), &iter); continue; } // TODO: If these aren't found but 20/22/23 are, an error will occur. if (reg_num == 19) iter_DMA_Len = iter; else if (reg_num == 21) iter_DMA_Src = iter; // Get the register value. // (prev_value == -1) means the register hasn't been updated yet. // TODO: DMA Length and DMA Src Addr are multibyte values. // With this method, they're only updated if the low byte is changed. // Maybe they should be displayed in a different area... reg_value = reg_vdp->data[reg_num]; if (prev_value != -1 && ((uint8_t)prev_value == reg_value)) { // Register hasn't been changed. Skip it. valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(lmRegList), &iter); continue; } // Create the hexadecimal value. szprintf(hex_value, sizeof(hex_value), "0x%02X", reg_value); // Get the description. vdpdbg_get_m5_reg_desc(reg_num, reg_value, reg_vdp, desc, sizeof(desc)); if (reg_num == 19 || reg_num == 20) DMA_Len_NeedsUpdate = TRUE; else if (reg_num >= 21 && reg_num <= 23) DMA_Src_NeedsUpdate = TRUE; // Set the value and description. gtk_list_store_set(GTK_LIST_STORE(lmRegList), &iter, 2, reg_value, // Value. 3, hex_value, // Value (in hex). 4, desc, -1); // Description. // Get the next list element. valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(lmRegList), &iter); } // Check if DMA Length or DMA Src Address need to be updated. if (DMA_Len_NeedsUpdate) { // DMA Length needs to be updated. vdpdbg_get_m5_dma_len_desc(reg_vdp, desc, sizeof(desc)); gtk_list_store_set(GTK_LIST_STORE(lmRegList), &iter_DMA_Len, 4, desc, -1); } if (DMA_Src_NeedsUpdate) { // DMA Src Address needs to be updated. vdpdbg_get_m5_dma_src_desc(reg_vdp, desc, sizeof(desc)); gtk_list_store_set(GTK_LIST_STORE(lmRegList), &iter_DMA_Src, 4, desc, -1); } }