Mercurial > hg > dmlib
comparison tools/ppl.c @ 2275:ba696835f66d
Add CLI-only mode to PPL (-C option).
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 18 Jun 2019 09:11:52 +0300 |
parents | e3f0eaf23f4f |
children | 2c90e455f006 |
comparison
equal
deleted
inserted
replaced
2274:a4c1fafd442a | 2275:ba696835f66d |
---|---|
59 int optOutFormat = JSS_AUDIO_S16, | 59 int optOutFormat = JSS_AUDIO_S16, |
60 optOutChannels = 2, | 60 optOutChannels = 2, |
61 optOutFreq = 48000, | 61 optOutFreq = 48000, |
62 optMuteOChannels = -1, | 62 optMuteOChannels = -1, |
63 optStartOrder = 0; | 63 optStartOrder = 0; |
64 BOOL optUsePlayTime = FALSE; | 64 BOOL optUsePlayTime = FALSE, |
65 optUseGUI = TRUE; | |
65 size_t optPlayTime; | 66 size_t optPlayTime; |
66 | 67 |
67 | 68 |
68 static const DMOptArg optList[] = | 69 static const DMOptArg optList[] = |
69 { | 70 { |
70 { 0, '?', "help", "Show this help", OPT_NONE }, | 71 { 0, '?', "help", "Show this help", OPT_NONE }, |
71 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, | 72 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, |
72 { 2, 0, "fs", "Fullscreen", OPT_NONE }, | 73 { 2, 0, "fs", "Fullscreen", OPT_NONE }, |
74 { 12, 'C', "cli", "Do not open GUI window", OPT_NONE }, | |
73 { 3, 'w', "window", "Initial window size/resolution -w 640x480", OPT_ARGREQ }, | 75 { 3, 'w', "window", "Initial window size/resolution -w 640x480", OPT_ARGREQ }, |
74 | 76 |
75 { 4, '1', "16bit", "16-bit output", OPT_NONE }, | 77 { 4, '1', "16bit", "16-bit output", OPT_NONE }, |
76 { 5, '8', "8bit", "8-bit output", OPT_NONE }, | 78 { 5, '8', "8bit", "8-bit output", OPT_NONE }, |
77 { 6, 'm', "mono", "Mono output", OPT_NONE }, | 79 { 6, 'm', "mono", "Mono output", OPT_NONE }, |
161 case 11: | 163 case 11: |
162 optPlayTime = atoi(optArg); | 164 optPlayTime = atoi(optArg); |
163 optUsePlayTime = TRUE; | 165 optUsePlayTime = TRUE; |
164 break; | 166 break; |
165 | 167 |
168 case 12: | |
169 optUseGUI = FALSE; | |
170 break; | |
171 | |
166 default: | 172 default: |
167 dmErrorMsg("Unimplemented option argument '%s'.\n", currArg); | 173 dmErrorMsg("Unimplemented option argument '%s'.\n", currArg); |
168 return FALSE; | 174 return FALSE; |
169 } | 175 } |
170 | 176 |
595 | 601 |
596 if (result != DMERR_OK) | 602 if (result != DMERR_OK) |
597 { | 603 { |
598 dmErrorMsg("Error loading module file, %d: %s\n", | 604 dmErrorMsg("Error loading module file, %d: %s\n", |
599 result, dmErrorStr(result)); | 605 result, dmErrorStr(result)); |
600 goto error_exit; | 606 goto exit; |
601 } | 607 } |
602 | 608 |
603 // Try to convert it | 609 // Try to convert it |
604 if ((result = jssConvertModuleForPlaying(eng.mod)) != DMERR_OK) | 610 if ((result = jssConvertModuleForPlaying(eng.mod)) != DMERR_OK) |
605 { | 611 { |
606 dmErrorMsg("Could not convert module for playing, %d: %s\n", | 612 dmErrorMsg("Could not convert module for playing, %d: %s\n", |
607 result, dmErrorStr(result)); | 613 result, dmErrorStr(result)); |
608 goto error_exit; | 614 goto exit; |
609 } | 615 } |
610 | 616 |
611 // Get font | |
612 result = dmf_open_memio(NULL, "pplfont.fnt", engineSetupFont, sizeof(engineSetupFont), &file); | |
613 if (result != DMERR_OK) | |
614 { | |
615 dmErrorMsg("Error opening font file 'pplfont.fnt', #%d: %s\n", | |
616 result, dmErrorStr(result)); | |
617 goto error_exit; | |
618 } | |
619 result = dmLoadBitmapFont(file, &font); | |
620 dmf_close(file); | |
621 if (result != DMERR_OK) | |
622 { | |
623 dmErrorMsg("Could not load font from file, %d: %s\n", | |
624 result, dmErrorStr(result)); | |
625 goto error_exit; | |
626 } | |
627 | |
628 SDL_Color pal[DMFONT_NPALETTE]; | |
629 for (int n = 0; n < DMFONT_NPALETTE; n++) | |
630 { | |
631 pal[n].r = pal[n].g = pal[n].b = 0; | |
632 pal[n].a = n > 0 ? 255 : 0; | |
633 } | |
634 dmSetBitmapFontPalette(font, pal, 0, DMFONT_NPALETTE); | |
635 | 617 |
636 // Initialize SDL components | 618 // Initialize SDL components |
637 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) | 619 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) |
638 { | 620 { |
639 dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError()); | 621 dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError()); |
640 goto error_exit; | 622 goto exit; |
641 } | 623 } |
642 initSDL = TRUE; | 624 initSDL = TRUE; |
643 | 625 |
644 | 626 |
645 // Initialize mixing device | 627 // Initialize mixing device |
648 | 630 |
649 eng.dev = jvmInit(optOutFormat, optOutChannels, optOutFreq, JMIX_AUTO); | 631 eng.dev = jvmInit(optOutFormat, optOutChannels, optOutFreq, JMIX_AUTO); |
650 if (eng.dev == NULL) | 632 if (eng.dev == NULL) |
651 { | 633 { |
652 dmErrorMsg("jvmInit() returned NULL\n"); | 634 dmErrorMsg("jvmInit() returned NULL\n"); |
653 goto error_exit; | 635 goto exit; |
654 } | 636 } |
655 | 637 |
656 switch (optOutFormat) | 638 switch (optOutFormat) |
657 { | 639 { |
658 case JSS_AUDIO_S16: eng.afmt.format = AUDIO_S16SYS; break; | 640 case JSS_AUDIO_S16: eng.afmt.format = AUDIO_S16SYS; break; |
660 case JSS_AUDIO_S8: eng.afmt.format = AUDIO_S8; break; | 642 case JSS_AUDIO_S8: eng.afmt.format = AUDIO_S8; break; |
661 case JSS_AUDIO_U8: eng.afmt.format = AUDIO_U8; break; | 643 case JSS_AUDIO_U8: eng.afmt.format = AUDIO_U8; break; |
662 default: | 644 default: |
663 dmErrorMsg("Unsupported audio format %d (could not set matching SDL format)\n", | 645 dmErrorMsg("Unsupported audio format %d (could not set matching SDL format)\n", |
664 optOutFormat); | 646 optOutFormat); |
665 goto error_exit; | 647 goto exit; |
666 } | 648 } |
667 | 649 |
668 eng.afmt.freq = optOutFreq; | 650 eng.afmt.freq = optOutFreq; |
669 eng.afmt.channels = optOutChannels; | 651 eng.afmt.channels = optOutChannels; |
670 eng.afmt.samples = optOutFreq / 16; | 652 eng.afmt.samples = optOutFreq / 16; |
674 // Open the audio device | 656 // Open the audio device |
675 if (SDL_OpenAudio(&eng.afmt, NULL) < 0) | 657 if (SDL_OpenAudio(&eng.afmt, NULL) < 0) |
676 { | 658 { |
677 dmErrorMsg("Couldn't open SDL audio: %s\n", | 659 dmErrorMsg("Couldn't open SDL audio: %s\n", |
678 SDL_GetError()); | 660 SDL_GetError()); |
679 goto error_exit; | 661 goto exit; |
680 } | 662 } |
681 audioInit = TRUE; | 663 audioInit = TRUE; |
682 | 664 |
683 // Initialize player | 665 // Initialize player |
684 if ((eng.plr = jmpInit(eng.dev)) == NULL) | 666 if ((eng.plr = jmpInit(eng.dev)) == NULL) |
685 { | 667 { |
686 dmErrorMsg("jmpInit() returned NULL\n"); | 668 dmErrorMsg("jmpInit() returned NULL\n"); |
687 goto error_exit; | 669 goto exit; |
688 } | 670 } |
689 | 671 |
690 jvmSetCallback(eng.dev, jmpExec, eng.plr); | 672 jvmSetCallback(eng.dev, jmpExec, eng.plr); |
691 jmpSetModule(eng.plr, eng.mod); | 673 jmpSetModule(eng.plr, eng.mod); |
692 jmpPlayOrder(eng.plr, optStartOrder); | 674 jmpPlayOrder(eng.plr, optStartOrder); |
698 jvmMute(eng.dev, optMuteOChannels, FALSE); | 680 jvmMute(eng.dev, optMuteOChannels, FALSE); |
699 eng.actChannel = optMuteOChannels; | 681 eng.actChannel = optMuteOChannels; |
700 muteState = TRUE; | 682 muteState = TRUE; |
701 } | 683 } |
702 | 684 |
703 // Open window | 685 if (optUseGUI) |
704 if ((eng.window = SDL_CreateWindow(dmProgName, | 686 { |
705 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | 687 // Get font |
706 eng.optScrWidth, eng.optScrHeight, | 688 result = dmf_open_memio(NULL, "pplfont.fnt", engineSetupFont, sizeof(engineSetupFont), &file); |
707 eng.optVFlags | SDL_WINDOW_RESIZABLE | 689 if (result != DMERR_OK) |
708 //| SDL_WINDOW_HIDDEN | 690 { |
709 )) == NULL) | 691 dmErrorMsg("Error opening font file 'pplfont.fnt', #%d: %s\n", |
710 { | 692 result, dmErrorStr(result)); |
711 dmErrorMsg("Can't create an SDL window: %s\n", SDL_GetError()); | 693 goto exit; |
712 goto error_exit; | 694 } |
713 } | 695 result = dmLoadBitmapFont(file, &font); |
714 | 696 dmf_close(file); |
715 SDL_SetWindowTitle(eng.window, dmProgDesc); | 697 if (result != DMERR_OK) |
716 | 698 { |
717 if ((eng.renderer = SDL_CreateRenderer(eng.window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL) | 699 dmErrorMsg("Could not load font from file, %d: %s\n", |
718 { | 700 result, dmErrorStr(result)); |
719 dmErrorMsg("Can't create an SDL renderer: %s\n", SDL_GetError()); | 701 goto exit; |
720 goto error_exit; | 702 } |
721 } | 703 |
722 | 704 SDL_Color pal[DMFONT_NPALETTE]; |
723 if (!dmInitializeVideo()) | 705 for (int n = 0; n < DMFONT_NPALETTE; n++) |
724 goto error_exit; | 706 { |
725 | 707 pal[n].r = pal[n].g = pal[n].b = 0; |
726 // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); | 708 pal[n].a = n > 0 ? 255 : 0; |
727 // SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); | 709 } |
710 dmSetBitmapFontPalette(font, pal, 0, DMFONT_NPALETTE); | |
711 | |
712 // Open window | |
713 if ((eng.window = SDL_CreateWindow(dmProgName, | |
714 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | |
715 eng.optScrWidth, eng.optScrHeight, | |
716 eng.optVFlags | SDL_WINDOW_RESIZABLE | |
717 //| SDL_WINDOW_HIDDEN | |
718 )) == NULL) | |
719 { | |
720 dmErrorMsg("Can't create an SDL window: %s\n", SDL_GetError()); | |
721 goto exit; | |
722 } | |
723 | |
724 SDL_SetWindowTitle(eng.window, dmProgDesc); | |
725 | |
726 if ((eng.renderer = SDL_CreateRenderer(eng.window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL) | |
727 { | |
728 dmErrorMsg("Can't create an SDL renderer: %s\n", SDL_GetError()); | |
729 goto exit; | |
730 } | |
731 | |
732 if (!dmInitializeVideo()) | |
733 goto exit; | |
734 | |
735 //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); | |
736 //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); | |
737 } | |
728 | 738 |
729 // okay, main loop here ... "play" module and print out info | 739 // okay, main loop here ... "play" module and print out info |
730 SDL_LockAudio(); | 740 SDL_LockAudio(); |
731 SDL_PauseAudio(0); | 741 SDL_PauseAudio(0); |
732 SDL_UnlockAudio(); | 742 SDL_UnlockAudio(); |
807 break; | 817 break; |
808 | 818 |
809 case SDLK_f: | 819 case SDLK_f: |
810 eng.optVFlags ^= SDL_WINDOW_FULLSCREEN_DESKTOP; | 820 eng.optVFlags ^= SDL_WINDOW_FULLSCREEN_DESKTOP; |
811 if (SDL_SetWindowFullscreen(eng.window, eng.optVFlags) != 0) | 821 if (SDL_SetWindowFullscreen(eng.window, eng.optVFlags) != 0) |
812 goto error_exit; | 822 goto exit; |
813 needUpdate = TRUE; | 823 needUpdate = TRUE; |
814 break; | 824 break; |
815 | 825 |
816 default: | 826 default: |
817 break; | 827 break; |
828 | 838 |
829 case SDL_WINDOWEVENT_RESIZED: | 839 case SDL_WINDOWEVENT_RESIZED: |
830 eng.optScrWidth = eng.event.window.data1; | 840 eng.optScrWidth = eng.event.window.data1; |
831 eng.optScrHeight = eng.event.window.data2; | 841 eng.optScrHeight = eng.event.window.data2; |
832 if (!dmInitializeVideo()) | 842 if (!dmInitializeVideo()) |
833 goto error_exit; | 843 goto exit; |
834 | 844 |
835 needUpdate = TRUE; | 845 needUpdate = TRUE; |
836 break; | 846 break; |
837 } | 847 } |
838 break; | 848 break; |
840 case SDL_QUIT: | 850 case SDL_QUIT: |
841 eng.exitFlag = TRUE; | 851 eng.exitFlag = TRUE; |
842 break; | 852 break; |
843 } | 853 } |
844 | 854 |
845 | 855 // Check for end of song |
846 #if 1 | |
847 JSS_LOCK(eng.plr); | 856 JSS_LOCK(eng.plr); |
848 JSSPattern *currPattern = eng.plr->pattern; | |
849 int currRow = eng.plr->row; | |
850 if (!eng.plr->isPlaying) | 857 if (!eng.plr->isPlaying) |
851 eng.exitFlag = TRUE; | 858 eng.exitFlag = TRUE; |
852 JSS_UNLOCK(eng.plr); | 859 JSS_UNLOCK(eng.plr); |
853 | 860 |
854 if (currRow != prevRow || needUpdate) | 861 if (optUseGUI) |
855 { | 862 { |
856 prevRow = currRow; | 863 // Check if we need to update screen |
857 needUpdate = TRUE; | |
858 } | |
859 | |
860 // Draw frame | |
861 if (needUpdate) | |
862 { | |
863 dmClearSurface(eng.screen, col.boxBg); | |
864 | |
865 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5, | |
866 "%s v%s by ccr/TNSP - (c) Copyright 2012-2018 TNSP", | |
867 dmProgDesc, dmProgVersion); | |
868 | |
869 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2), | |
870 "Song: '%s'", | |
871 eng.mod->moduleName); | |
872 | |
873 dmDisplayPattern(eng.screen, 5, 5 + (font->height + 2) * 3 + 4, | |
874 eng.screen->w - 6, | |
875 eng.screen->h * 0.8, | |
876 currPattern, currRow); | |
877 | |
878 JSS_LOCK(eng.plr); | 864 JSS_LOCK(eng.plr); |
879 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2) * 2, | 865 JSSPattern *currPattern = eng.plr->pattern; |
880 "Tempo: %3d | Speed: %3d | Row: %3d/%-3d | Order: %3d/%-3d | Pattern: %3d/%-3d", | 866 int currRow = eng.plr->row; |
881 eng.plr->tempo, eng.plr->speed, | |
882 eng.plr->row, (eng.plr->pattern != NULL) ? eng.plr->pattern->nrows : 0, | |
883 eng.plr->order + 1, eng.mod->norders, | |
884 eng.plr->npattern, eng.mod->npatterns); | |
885 JSS_UNLOCK(eng.plr); | 867 JSS_UNLOCK(eng.plr); |
886 needRender = TRUE; | 868 |
887 } | 869 if (currRow != prevRow || needUpdate) |
888 | 870 { |
889 if (needUpdate || currTick - prevTick >= (eng.pauseFlag ? 100 : 20)) | 871 prevRow = currRow; |
890 { | 872 needUpdate = TRUE; |
891 JSS_LOCK(eng.dev); | 873 } |
892 dmDisplayChannels(eng.screen, 5, eng.screen->h * 0.8 + 5, | 874 |
893 eng.screen->w - 5, eng.screen->h - 5, eng.dev); | 875 // Draw frame |
894 JSS_UNLOCK(eng.dev); | 876 if (needUpdate) |
895 needRender = TRUE; | 877 { |
896 } | 878 dmClearSurface(eng.screen, col.boxBg); |
897 | 879 |
898 if (needUpdate) | 880 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5, |
899 prevTick = currTick; | 881 "%s v%s by ccr/TNSP - (c) Copyright 2012-2018 TNSP", |
900 | 882 dmProgDesc, dmProgVersion); |
901 #endif | 883 |
902 // Flip screen | 884 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2), |
903 if (needRender) | 885 "Song: '%s'", |
904 { | 886 eng.mod->moduleName); |
905 SDL_Surface dst; | 887 |
906 SDL_LockTexture(eng.texture, NULL, &dst.pixels, &dst.pitch); | 888 dmDisplayPattern(eng.screen, 5, 5 + (font->height + 2) * 3 + 4, |
907 | 889 eng.screen->w - 6, |
908 if (dst.pitch != eng.screen->pitch) | 890 eng.screen->h * 0.8, |
909 eng.exitFlag = TRUE; | 891 currPattern, currRow); |
910 else | 892 |
911 memcpy(dst.pixels, eng.screen->pixels, eng.screen->h * dst.pitch); | 893 JSS_LOCK(eng.plr); |
912 | 894 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2) * 2, |
913 SDL_UnlockTexture(eng.texture); | 895 "Tempo: %3d | Speed: %3d | Row: %3d/%-3d | Order: %3d/%-3d | Pattern: %3d/%-3d", |
914 | 896 eng.plr->tempo, eng.plr->speed, |
915 //SDL_RenderClear(eng.renderer); | 897 eng.plr->row, (eng.plr->pattern != NULL) ? eng.plr->pattern->nrows : 0, |
916 SDL_RenderCopy(eng.renderer, eng.texture, NULL, NULL); | 898 eng.plr->order + 1, eng.mod->norders, |
917 SDL_RenderPresent(eng.renderer); | 899 eng.plr->npattern, eng.mod->npatterns); |
918 } | 900 JSS_UNLOCK(eng.plr); |
901 needRender = TRUE; | |
902 } | |
903 | |
904 if (needUpdate || currTick - prevTick >= (eng.pauseFlag ? 100 : 20)) | |
905 { | |
906 JSS_LOCK(eng.dev); | |
907 dmDisplayChannels(eng.screen, 5, eng.screen->h * 0.8 + 5, | |
908 eng.screen->w - 5, eng.screen->h - 5, eng.dev); | |
909 JSS_UNLOCK(eng.dev); | |
910 needRender = TRUE; | |
911 } | |
912 | |
913 if (needUpdate) | |
914 prevTick = currTick; | |
915 | |
916 // Flip screen | |
917 if (needRender) | |
918 { | |
919 SDL_Surface dst; | |
920 SDL_LockTexture(eng.texture, NULL, &dst.pixels, &dst.pitch); | |
921 | |
922 if (dst.pitch != eng.screen->pitch) | |
923 eng.exitFlag = TRUE; | |
924 else | |
925 memcpy(dst.pixels, eng.screen->pixels, eng.screen->h * dst.pitch); | |
926 | |
927 SDL_UnlockTexture(eng.texture); | |
928 | |
929 //SDL_RenderClear(eng.renderer); | |
930 SDL_RenderCopy(eng.renderer, eng.texture, NULL, NULL); | |
931 SDL_RenderPresent(eng.renderer); | |
932 } | |
933 } // optUseGUI | |
919 | 934 |
920 SDL_Delay(eng.pauseFlag ? 100 : 30); | 935 SDL_Delay(eng.pauseFlag ? 100 : 30); |
921 } | 936 } |
922 | 937 |
923 error_exit: | 938 exit: |
924 if (eng.texture != NULL) | 939 // Cleanup |
925 SDL_DestroyTexture(eng.texture); | 940 if (optUseGUI) |
926 | 941 { |
927 if (eng.renderer != NULL) | 942 dmMsg(1, "GUI shutdown.\n"); |
928 SDL_DestroyRenderer(eng.renderer); | 943 if (eng.texture != NULL) |
929 | 944 SDL_DestroyTexture(eng.texture); |
930 if (eng.window != NULL) | 945 |
931 SDL_DestroyWindow(eng.window); | 946 if (eng.renderer != NULL) |
932 | 947 SDL_DestroyRenderer(eng.renderer); |
933 if (eng.screen != NULL) | 948 |
934 SDL_FreeSurface(eng.screen); | 949 if (eng.window != NULL) |
935 | 950 SDL_DestroyWindow(eng.window); |
936 dmMsg(0, "Audio shutdown.\n"); | 951 |
952 if (eng.screen != NULL) | |
953 SDL_FreeSurface(eng.screen); | |
954 | |
955 dmFreeBitmapFont(font); | |
956 } | |
957 | |
958 dmMsg(1, "Audio shutdown.\n"); | |
937 if (audioInit) | 959 if (audioInit) |
938 { | 960 { |
939 SDL_LockAudio(); | 961 SDL_LockAudio(); |
940 SDL_PauseAudio(1); | 962 SDL_PauseAudio(1); |
941 SDL_UnlockAudio(); | 963 SDL_UnlockAudio(); |
944 | 966 |
945 jmpClose(eng.plr); | 967 jmpClose(eng.plr); |
946 jvmClose(eng.dev); | 968 jvmClose(eng.dev); |
947 jssFreeModule(eng.mod); | 969 jssFreeModule(eng.mod); |
948 | 970 |
949 dmFreeBitmapFont(font); | 971 dmMsg(1, "Shut down SDL.\n"); |
950 | |
951 if (initSDL) | 972 if (initSDL) |
952 SDL_Quit(); | 973 SDL_Quit(); |
953 | 974 |
954 jssClose(); | 975 jssClose(); |
955 | 976 |