static void change_subsong(int subsong) { song.cur_subsong = subsong; uade_put_long(SCORE_SUBSONG, subsong); uade_send_amiga_message(AMIGAMSG_SETSUBSONG); flush_sound(); }
/* this is called for each played song from newcpu.c/m68k_reset() */ void uade_reset(void) { /* don't load anything under 0x1000 (execbase top at $1000) */ const int modnameaddr = 0x00400; const int scoreaddr = 0x01000; const int userstack = 0x08500; const int superstack = 0x08f00; const int playeraddr = 0x09000; int relocaddr; int modaddr; int len; FILE *file; int bytesread; uint8_t command[UADE_MAX_MESSAGE_SIZE]; struct uade_msg *um = (struct uade_msg *) command; int ret; nextsong: /* IMPORTANT: It seems that certain players don't work totally reliably if memory contains trash from previous songs. To be certain that each song is played from the same initial state of emulator we clear the memory from 0x400 to 'uade_highmem' each time a new song is played */ uade_highmem = 0; while (uade_highmem < 0x800000) { if (!valid_address(0, uade_highmem + 0x10000)) break; uade_highmem += 0x10000; } if (uade_highmem < 0x80000) { fprintf(stderr, "uadecore: There must be at least 512 KiB of amiga memory (%d bytes found).\n", uade_highmem); exit(-1); } if (uade_highmem < 0x200000) { fprintf(stderr, "uadecore: Warning: highmem == 0x%x (< 0x200000)!\n", uade_highmem); } memset(get_real_address(0), 0, uade_highmem); song.cur_subsong = song.min_subsong = song.max_subsong = 0; ret = uade_receive_string(song.scorename, UADE_COMMAND_SCORE, sizeof(song.scorename), &uadeipc); if (ret == 0) { fprintf(stderr, "uadecore: No more songs to play.\n"); exit(0); } else if (ret < 0) { fprintf(stderr, "uadecore: Invalid input. Expected score name.\n"); exit(-1); } // printf("got scorename %s\n",song.scorename); ret = uade_receive_string(song.playername, UADE_COMMAND_PLAYER, sizeof(song.playername), &uadeipc); if (ret == 0) { printf("uadecore: Expected player name. Got nothing.\n"); exit(-1); } else if (ret < 0) { printf( "uadecore: Invalid input. Expected player name.\n"); exit(-1); } // printf("got playername %s\n",song.playername); if (uade_dirname(uade_player_dir, song.playername, sizeof(uade_player_dir)) == NULL) { printf( "uadecore: Invalid dirname with player: %s\n", song.playername); exit(-1); } ret = uade_receive_message(um, sizeof command, &uadeipc); if (ret == 0) { printf("uadecore: Expected module name. Got nothing.\n"); exit(-1); } else if (ret < 0) { printf( "uadecore: Invalid input. Expected module name.\n"); exit(-1); } assert(um->msgtype == UADE_COMMAND_MODULE); if (um->size == 0) { song.modulename[0] = 0; } else { assert(um->size == (strlen((char *) um->data) + 1)); strlcpy(song.modulename, (char *) um->data, sizeof(song.modulename)); } // printf("got modulename %s\n",song.modulename); uade_set_automatic_song_end(1); uade_put_long(SCORE_EXEC_DEBUG, uade_execdebugboolean ? 0x12345678 : 0); uade_put_long(SCORE_VOLUME_TEST, voltestboolean); uade_put_long(SCORE_DMA_WAIT, uade_dmawait); uade_put_long(SCORE_MODULECHANGE, disable_modulechange); bytesread = uade_safe_load_name(playeraddr, song.playername, "player", uade_highmem - playeraddr); if (bytesread > (uade_highmem - playeraddr)) { fprintf (stderr, "uadecore: Player %s too big a file (%d bytes).\n", song.playername, bytesread); goto skiptonextsong; } if (bytesread == 0) { goto skiptonextsong; } /* fprintf(stderr, "uadecore: player '%s' (%d bytes)\n", song.playername, bytesread); */ /* set player executable address for relocator */ uade_put_long(SCORE_PLAYER_ADDR, playeraddr); len = uade_calc_reloc_size((uae_u32 *) get_real_address(playeraddr), (uae_u32 *) get_real_address(playeraddr + bytesread)); if (!len) { fprintf(stderr, "uadecore: Problem with reloc calculation.\n"); goto skiptonextsong; } relocaddr = ((playeraddr + bytesread) & 0x7FFFF000) + 0x4000; /* + 0x4000 for hippel coso (wasseremu) */ modaddr = ((relocaddr + len) & 0x7FFFF000) + 0x2000; if (modaddr <= relocaddr) { /* this is very bad because sound core memory allocation will fail */ fprintf(stderr, "uadecore: Warning: modaddr <= relocaddr: 0x%x <= 0x%x\n", modaddr, relocaddr); } uade_put_long(SCORE_RELOC_ADDR, relocaddr); /*address for relocated player*/ uade_put_long(SCORE_MODULE_ADDR, modaddr); /* set module address */ uade_put_long(SCORE_MODULE_LEN, 0); /* set module size to zero */ uade_put_long(SCORE_MODULE_NAME_ADDR, 0); /* mod name address pointer */ /* load the module if available */ if (song.modulename[0]) { bytesread = uade_safe_load_name(modaddr, song.modulename, "module", uade_highmem - modaddr); if (bytesread > (uade_highmem - playeraddr)) { fprintf (stderr, "uadecore: Module %s too big a file (%d bytes).\n", song.modulename, bytesread); goto skiptonextsong; } if (bytesread == 0) { goto skiptonextsong; } uade_put_long(SCORE_MODULE_LEN, bytesread); if (!valid_address(modnameaddr, strlen(song.modulename) + 1)) { fprintf(stderr, "uadecore: Invalid address for modulename.\n"); goto skiptonextsong; } strlcpy((char *) get_real_address(modnameaddr), song.modulename, 1024); uade_put_long(SCORE_MODULE_NAME_ADDR, modnameaddr); } else { if (!valid_address(modnameaddr, strlen(song.playername) + 1)) { fprintf(stderr, "uadecore: Invalid address for playername.\n"); goto skiptonextsong; } strlcpy((char *) get_real_address(modnameaddr), song.playername, 1024); uade_put_long(SCORE_MODULE_NAME_ADDR, modnameaddr); bytesread = 0; } /* load sound core (score) */ if ((file = fopen(song.scorename, "rb"))) { bytesread = uade_safe_load(scoreaddr, file, uade_highmem - scoreaddr); fclose(file); } else { fprintf (stderr, "uadecore: Can not load score (%s).\n", song.scorename); goto skiptonextsong; } m68k_areg(regs,7) = scoreaddr; m68k_setpc(scoreaddr); /* obey player format checking */ uade_put_long(SCORE_FORCE, 0); /* set default subsong */ uade_put_long(SCORE_SET_SUBSONG, 0); uade_put_long(SCORE_SUBSONG, 0); /* set PAL mode */ uade_set_ntsc(0); /* pause bits (don't care!), for debugging purposes only */ uade_put_long(SCORE_PREPAUSE, 0); uade_put_long(SCORE_POSTPAUSE, 0); /* set user and supervisor stack pointers */ uade_put_long(SCORE_USER_STACK, userstack); uade_put_long(SCORE_SUPER_STACK, superstack); /* no message for score */ uade_put_long(SCORE_OUTPUT_MSG, 0); if ((userstack - (scoreaddr + bytesread)) < 0x1000) fprintf(stderr, "uadecore: Amiga stack overrun warning.\n"); flush_sound(); /* note that uade_speed_hack can be negative (meaning that uade never uses speed hack, even if it's requested by the amiga player)! */ uade_time_critical = 0; if (uade_speed_hack > 0) { uade_time_critical = 1; } uade_reboot = 0; uade_audio_output = 0; uade_audio_skip = 0; old_ledstate = gui_ledstate; if (uade_receive_short_message(UADE_COMMAND_TOKEN, &uadeipc)) { fprintf(stderr, "uadecore: Can not receive token in uade_reset().\n"); exit(-1); } if (uade_send_short_message(UADE_REPLY_CAN_PLAY, &uadeipc)) { fprintf(stderr, "uadecore: Can not send 'CAN_PLAY' reply.\n"); exit(-1); } if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) { fprintf(stderr, "uadecore: Can not send token from uade_reset().\n"); exit(-1); } set_sound_freq(UADE_DEFAULT_FREQUENCY); epoptionsize = 0; return; skiptonextsong: fprintf(stderr, "uadecore: Can not play. Reboot.\n"); if (uade_receive_short_message(UADE_COMMAND_TOKEN, &uadeipc)) { fprintf(stderr, "uadecore: Can not receive token in uade_reset().\n"); exit(-1); } if (uade_send_short_message(UADE_REPLY_CANT_PLAY, &uadeipc)) { fprintf(stderr, "uadecore: Can not send 'CANT_PLAY' reply.\n"); exit(-1); } if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) { fprintf(stderr, "uadecore: Can not send token from uade_reset().\n"); exit(-1); } goto nextsong; }
LRESULT CALLBACK MainWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; int h, w, key = 0, shift; static old_res = TRUE; xyxy *p = (xyxy *)lParam; switch (nMsg) { case WM_COMMAND: /* Handle menu options */ switch (LOWORD(wParam)) { case ITEM_OPTIONS_RES_LOW: opt.hires = FALSE; refresh_screen(); break; case ITEM_OPTIONS_RES_HIGH: opt.cgaemu = FALSE; opt.hires = TRUE; refresh_screen(); break; case ITEM_OPTIONS_PAL_CGA: opt.cgaemu = TRUE; old_res = opt.hires; opt.hires = FALSE; refresh_screen(); break; case ITEM_OPTIONS_PAL_EGA: if (opt.cgaemu) opt.hires = old_res; opt.cgaemu = FALSE; init_palette (ega_palette); set_palette (palette, 0, 32); refresh_screen(); break; case ITEM_OPTIONS_PAL_NEW: if (opt.cgaemu) opt.hires = old_res; opt.cgaemu = FALSE; init_palette (new_palette); set_palette (palette, 0, 32); refresh_screen(); break; case ITEM_OPTIONS_SIZE_SMALL: scale = 1; resize_window(hwnd); set_putpixels_method(); refresh_screen(); break; case ITEM_OPTIONS_SIZE_LARGE: scale = 2; resize_window (hwnd); set_putpixels_method(); refresh_screen(); break; case ITEM_OPTIONS_RATIO_43: opt.fixratio = 1; resize_window(hwnd); set_putpixels_method(); refresh_screen(); break; case ITEM_OPTIONS_RATIO_85: opt.fixratio = 0; resize_window(hwnd); set_putpixels_method(); refresh_screen(); break; case ITEM_FILE_OPEN: open_file (hwnd); break; case ITEM_HELP_ABOUT: DialogBox (GetModuleHandle(NULL), MAKEINTRESOURCE(DIALOG_ABOUT), hwnd, AboutDlgProc); break; case ITEM_FILE_EXIT: deinit_vidmode (); exit (0); } break; case WM_PUT_BLOCK: hdc = GetDC (hwnd); w = p->x2 - p->x1 + 1; h = p->y2 - p->y1 + 1; EnterCriticalSection (&g_screen.cs); StretchDIBits ( hdc, p->x1, p->y1, w, h, p->x1, ysize - p->y2 - 1, w, h, g_screen.screen_pixels, g_screen.binfo, DIB_RGB_COLORS, SRCCOPY); LeaveCriticalSection (&g_screen.cs); ReleaseDC (hwnd, hdc); break; case WM_DESTROY: deinit_vidmode (); exit (-1); case WM_PAINT: hdc = BeginPaint (hwnd, &ps); EnterCriticalSection(&g_screen.cs); StretchDIBits( hdc, 0, 0, xsize, ysize, 0, 0, xsize, ysize, g_screen.screen_pixels, g_screen.binfo, DIB_RGB_COLORS, SRCCOPY); EndPaint (hwnd, &ps); LeaveCriticalSection(&g_screen.cs); return 0; /* Multimedia functions * (Damn! The CALLBACK_FUNCTION parameter doesn't work!) */ case MM_WOM_DONE: flush_sound ((PWAVEHDR) lParam); return 0; case WM_LBUTTONDOWN: key = BUTTON_LEFT; mouse.button = 1; update_mouse_pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case WM_RBUTTONDOWN: key = BUTTON_RIGHT; mouse.button = 2; update_mouse_pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case WM_LBUTTONUP: case WM_RBUTTONUP: mouse.button = FALSE; return 0; case WM_MOUSEMOVE: update_mouse_pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: /* report ("%02x\n", (int)wParam); */ key = (int)wParam; shift = GetAsyncKeyState (VK_SHIFT) & 0x8000; switch (key) { case VK_SHIFT: case VK_CONTROL: case VK_MENU: key = 0; break; case VK_UP: case VK_NUMPAD8: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_UP; break; case VK_LEFT: case VK_NUMPAD4: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_LEFT; break; case VK_DOWN: case VK_NUMPAD2: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_DOWN; break; case VK_RIGHT: case VK_NUMPAD6: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_RIGHT; break; case VK_HOME: case VK_NUMPAD7: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_UP_LEFT; break; case VK_PRIOR: case VK_NUMPAD9: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_UP_RIGHT; break; case VK_NEXT: case VK_NUMPAD3: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_DOWN_RIGHT; break; case VK_END: case VK_NUMPAD1: if (lParam & REPEATED_KEYMASK) return 0; key = KEY_DOWN_LEFT; break; case VK_CLEAR: case VK_NUMPAD5: key = KEY_STATIONARY; break; case VK_RETURN: key = KEY_ENTER; break; case VK_ADD: key = '+'; break; case VK_SUBTRACT: key = '-'; break; case VK_TAB: key = 0x0009; break; case VK_F1: key = 0x3b00; break; case VK_F2: key = 0x3c00; break; case VK_F3: key = 0x3d00; break; case VK_F4: key = 0x3e00; break; case VK_F5: key = 0x3f00; break; case VK_F6: key = 0x4000; break; case VK_F7: key = 0x4100; break; case VK_F8: key = 0x4200; break; case VK_F9: key = 0x4300; break; case VK_F10: key = 0x4400; break; case VK_F11: key = KEY_STATUSLN; break; case VK_F12: key = KEY_PRIORITY; break; case VK_ESCAPE: key = 0x1b; break; case 0xba: key = shift ? ':' : ';'; break; case 0xbb: key = shift ? '+' : '='; break; case 0xbc: key = shift ? '<' : ','; break; case 0xbd: key = shift ? '_' : '-'; break; case 0xbe: key = shift ? '>' : '.'; break; case 0xbf: key = shift ? '?' : '/'; break; case 0xdb: key = shift ? '{' : '['; break; case 0xdc: key = shift ? '|' : '\\'; break; case 0xdd: key = shift ? '}' : ']'; break; case 0xde: key = shift ? '"' : '\''; break; case 192: key = shift ? '~' : '`'; break; default: if (!isalpha (key)) break; /* Must exist a better way to do that! */ if (GetKeyState (VK_CAPITAL) & 0x1) { if (GetAsyncKeyState (VK_SHIFT) & 0x8000) key = key + 32; } else { if (!(GetAsyncKeyState (VK_SHIFT) & 0x8000)) key = key + 32; } /* Control and Alt modifier */ if (GetAsyncKeyState (VK_CONTROL) & 0x8000) key = (key & ~0x20) - 0x40; else if (GetAsyncKeyState (VK_MENU) & 0x8000) key = scancode_table[(key & ~0x20) - 0x41] << 8; break; } // this causes assertions in VS.NET // _D (": key = 0x%02x ('%c')", key, isprint(key) ? key : '?'); break; }; /* Keyboard message handled */ if (key) { key_enqueue (key); return 0; } return DefWindowProc (hwnd, nMsg, wParam, lParam); }