void AUDxPER (int nr, uae_u16 v) { TEXT_SCOPE(cycles, nr, PET_PER, v); update_audio (); if (v == 0) v = 65535; else if (v < 16) { /* With the risk of breaking super-cool players, we limit the value to 16 to save cpu time on not so powerful machines. robocop customs use low values for example. */ if (!audperhack) { audperhack = 1; uade_send_debug("Eagleplayer inserted %d into aud%dper.", v, nr); } v = 16; } audio_channel[nr].per = v; }
/* This is called when an eagleplayer queries for attributes. The query result is returned through 'dst', and the result is at most maxlen bytes long. 'src' contains the full query. */ static int get_info_for_ep(char *dst, char *src, int maxlen) { int ret = -1; if (strcasecmp(src, "eagleoptions") == 0) { if (epoptionsize > 0) { if (epoptionsize <= maxlen) { ret = epoptionsize; memcpy(dst, epoptions, ret); } else { fprintf(stderr, "uadecore: too long options: %s maxlen = %d\n", epoptions, maxlen); } } else { ret = 0; } } else { uade_send_debug("Unknown eagleplayer attribute queried: %s\n", src); } return ret; }
/* last part of the audio system pipeline */ void uade_check_sound_buffers(int bytes) { uint8_t space[UADE_MAX_MESSAGE_SIZE]; struct uade_msg *um = (struct uade_msg *) space; //YOYO optimization : no swap since I'm using no network but only buffers /* transmit in big endian format, so swap if little endian */ // if (uade_big_endian == 0) // uade_swap_buffer_bytes(sndbuffer, bytes); /* LED state changes are reported here because we are in send state and this place is heavily rate limited. */ if (old_ledstate != gui_ledstate) { old_ledstate = gui_ledstate; uade_send_debug("LED is %s", gui_ledstate ? "ON" : "OFF"); } um->msgtype = UADE_REPLY_DATA; um->size = bytes; memcpy(um->data, sndbuffer, bytes); if (uade_send_message(um, &uadeipc)) { fprintf(stderr, "uadecore: Could not send sample data.\n"); exit(-1); } uade_read_size -= bytes; assert(uade_read_size >= 0); if (uade_read_size == 0) { /* if all requested data has been sent, move to S state */ if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) { fprintf(stderr, "uadecore: Could not send token (after samples).\n"); exit(-1); } uade_handle_r_state(); } }
void uade_get_amiga_message(void) { uae_u8 *ptr; uae_u8 *nameptr; FILE *file; int x; unsigned int mins, maxs, curs; int status; int src, dst, off, len; char tmpstr[256]; char *srcstr, *dststr; uint32_t *u32ptr; uint8_t space[256]; struct uade_msg *um = (struct uade_msg *) space; x = uade_get_u32(SCORE_INPUT_MSG); /* message type from amiga */ switch (x) { case AMIGAMSG_SONG_END: uade_song_end("player", 0); break; case AMIGAMSG_SUBSINFO: mins = uade_get_u32(SCORE_MIN_SUBSONG); maxs = uade_get_u32(SCORE_MAX_SUBSONG); curs = uade_get_u32(SCORE_CUR_SUBSONG); /* Brain damage in TFMX BC Kid Despair */ if (maxs < mins) { uade_send_debug("Odd subsongs. Eagleplayer reported (min, cur, max) == (%u, %u, %u)", mins, curs, maxs); maxs = mins; } /* Brain damage in Bubble bobble custom */ if (curs > maxs) { uade_send_debug("Odd subsongs. Eagleplayer reported (min, cur, max) == (%u, %u, %u)", mins, curs, maxs); maxs = curs; } um->msgtype = UADE_REPLY_SUBSONG_INFO; um->size = 12; u32ptr = (uint32_t *) um->data; u32ptr[0] = htonl(mins); u32ptr[1] = htonl(maxs); u32ptr[2] = htonl(curs); if (uade_send_message(um, &uadeipc)) { fprintf(stderr, "uadecore: Could not send subsong info message.\n"); exit(-1); } break; case AMIGAMSG_PLAYERNAME: strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr); uade_send_string(UADE_REPLY_PLAYERNAME, tmpstr, &uadeipc); break; case AMIGAMSG_MODULENAME: strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr); uade_send_string(UADE_REPLY_MODULENAME, tmpstr, &uadeipc); break; case AMIGAMSG_FORMATNAME: strlcpy(tmpstr, (char *) get_real_address(0x204), sizeof tmpstr); uade_send_string(UADE_REPLY_FORMATNAME, tmpstr, &uadeipc); break; case AMIGAMSG_GENERALMSG: uade_send_debug((char *) get_real_address(0x204)); break; case AMIGAMSG_CHECKERROR: uade_song_end("module check failed", 1); break; case AMIGAMSG_SCORECRASH: if (uade_debug) { fprintf(stderr, "uadecore: Score crashed.\n"); activate_debugger(); break; } uade_song_end("score crashed", 1); break; case AMIGAMSG_SCOREDEAD: if (uade_debug) { fprintf(stderr, "uadecore: Score is dead.\n"); activate_debugger(); break; } uade_song_end("score died", 1); break; case AMIGAMSG_LOADFILE: /* load a file named at 0x204 (name pointer) to address pointed by 0x208 and insert the length to 0x20C */ src = uade_get_u32(0x204); if (!uade_valid_string(src)) { fprintf(stderr, "uadecore: Load name in invalid address range.\n"); break; } nameptr = get_real_address(src); if ((file = uade_open_amiga_file((char *) nameptr, uade_player_dir))) { dst = uade_get_u32(0x208); len = uade_safe_load(dst, file, uade_highmem - dst); fclose(file); file = NULL; uade_put_long(0x20C, len); uade_send_debug("load success: %s ptr 0x%x size 0x%x", nameptr, dst, len); } else { uade_send_debug("load: file not found: %s", nameptr); } break; case AMIGAMSG_READ: src = uade_get_u32(0x204); if (!uade_valid_string(src)) { fprintf(stderr, "uadecore: Read name in invalid address range.\n"); break; } nameptr = get_real_address(src); dst = uade_get_u32(0x208); off = uade_get_u32(0x20C); len = uade_get_u32(0x210); if ((file = uade_open_amiga_file((char *) nameptr, uade_player_dir))) { if (fseek(file, off, SEEK_SET)) { perror("can not fseek to position"); x = 0; } else { x = uade_safe_load(dst, file, len); if (x > len) x = len; } fclose(file); uade_send_debug("read %s dst 0x%x off 0x%x len 0x%x res 0x%x", nameptr, dst, off, len, x); uade_put_long(0x214, x); } else { uade_send_debug("read: file not found: %s", nameptr); uade_put_long(0x214, 0); } break; case AMIGAMSG_FILESIZE: src = uade_get_u32(0x204); if (!uade_valid_string(src)) { fprintf(stderr, "uadecore: Filesize name in invalid address range.\n"); break; } nameptr = get_real_address(src); if ((file = uade_open_amiga_file((char *) nameptr, uade_player_dir))) { fseek(file, 0, SEEK_END); len = ftell(file); fclose(file); uade_put_long(0x208, len); uade_put_long(0x20C, -1); uade_send_debug("filesize: file %s res 0x%x", nameptr, len); } else { uade_put_long(0x208, 0); uade_put_long(0x20C, 0); uade_send_debug("filesize: file not found: %s", nameptr); } break; case AMIGAMSG_TIME_CRITICAL: uade_time_critical = uade_get_u32(0x204) ? 1 : 0; if (uade_speed_hack < 0) { /* a negative value forbids use of speed hack */ uade_time_critical = 0; } break; case AMIGAMSG_GET_INFO: src = uade_get_u32(0x204); dst = uade_get_u32(0x208); len = uade_get_u32(0x20C); if (!uade_valid_string(src)) { fprintf(stderr, "uadecore: get info: Invalid src: 0x%x\n", src); break; } if (len <= 0) { fprintf(stderr, "uadecore: get info: len = %d\n", len); break; } if (!valid_address(dst, len)) { fprintf(stderr, "uadecore: get info: Invalid dst: 0x%x\n", dst); break; } srcstr = (char *) get_real_address(src); dststr = (char *) get_real_address(dst); uade_send_debug("score issued an info request: %s (maxlen %d)\n", srcstr, len); len = get_info_for_ep(dststr, srcstr, len); /* Send printable debug */ do { size_t i; size_t maxspace = sizeof space; if (len <= 0) { maxspace = 1; } else { if (len < maxspace) maxspace = len; } for (i = 0; i < maxspace; i++) { space[i] = dststr[i]; if (space[i] == 0) space[i] = ' '; } if (i < maxspace) { space[i] = 0; } else { space[maxspace - 1] = 0; } uade_send_debug("reply to score: %s (total len %d)\n", space, len); } while (0); uade_put_long(0x20C, len); break; case AMIGAMSG_START_OUTPUT: uade_audio_output = 1; uade_send_debug("Starting audio output at %d", uade_audio_skip); break; default: fprintf(stderr,"uadecore: Unknown message from score (%d)\n", x); break; } }