// Project: FLMODPLAY - a Amiga MODule Replayer // Created: 2017-03-29 // by Xaby aka Folker // for App Game Kit 2 Tier 1 Basic // Useing : // MOD Player Tutorial by FireLight ■ Copyright (c) Brett Paterson 1994-95 ■ // Amiga ProTracker Info by Lars Hamre // http://web.eject.co.za/gob/ Vee & GoB MOD Player in Pascal // Thanks to the Modarchive.org Function FEN_TextXY(Text$,x,y,cID) // FEN_ for F-Engine ... t1 = CreateText(Text$) SetTextFont(t1,fnt) SetTextBold(t1,1) SetTextSize(t1,20) // cID could be a Color from a 16-Color-Palette r=250/16*cID g=250/16*(mod(cID,4))*4+10 b=mod(cID,5)*16*3+10 // 51 ... * 5 = 255 SetTextColor(t1,r,g,b,255) SetTextPosition(t1,x,y) EndFunction t1 Function Init() // show all errors SetErrorMode(2) // set window properties SetWindowTitle( "FLMODPLAY" ) SetWindowSize( 800, 600, 0 ) // set display properties SetVirtualResolution( 800, 600 ) SetOrientationAllowed( 1, 1, 1, 1 ) SetSyncRate( 0, 0 ) // 30fps instead of 60 to save battery, 0 for MAX UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts //SetAntialiasMode(1) //-------------------- Better Visuals --------------------------- global fnt fnt = LoadFont("Courier New") // M-Space-Letters Endfunction //---------------------- helper functions -------------------------- function GetMemblockUnsignedShort(memID, offset) // GetMemblockWord a = GetMemblockByte( memID, offset ) b = GetMemblockByte( memID, offset+1 ) result = b*256+a // or a*256+b // Intel? in S3M endfunction result function GetMemblockWord(memID, offset) // GetMemblockUnsignedShort a = GetMemblockByte( memID, offset ) b = GetMemblockByte( memID, offset+1 ) result = a*256+b // or b*256+a // Motorola? in MOD endfunction result //-------------------- Amiga ProTracker Module ------------------- // by xaby //---------------------------------------------------------------- Type APT_MOD_Sample // 30 Bytes sample_name$ as String // 22 Chars sample_length as integer // Unsigned Short / Word / 2 Bytes fine_tune as integer // 1 Byte volume as integer // 1 Byte loop_start as integer // 2 Bytes loop_length as integer // 2 Bytes samp_buff as integer // SoundID? or MemBlock-ID EndType Type APT_MOD_Instrument a EndType Type APT_MOD_File_Header a EndType Type APT_MOD_Note a EndType /* Type APT_MOD_Pattern // Notes per Channel EndType */ Type APT_MOD_File // Amiga ProTracker Module File //Header as APT_MOD_File_Header module_name$ as String // [0..19] + NUL (20 Bytes) modtype$ as String // 4 Chars channels as integer sample as APT_MOD_Sample[31] UniqueSamples as Integer // Tests instrument as APT_MOD_Instrument[31] //songlength as Integer // 1..128 NumOrders as Integer //1..128 PatternsByte as Integer // =127 at 951 in file, in some files = 0 order as Integer[128] // at 952 in file, references to a patternID NumPatterns as Integer // is MaxPatterns //pattern as APT_MOD_Pattern[128] padme as Integer // *pointer to MemBlock with all Channels and Notes, Dublicate in Memory!? error$ as String // for error-handling EndType Function Load_APT_MOD_File(filename$) // returns Sound-Handle apt_mod as APT_MOD_File mem = CreateMemblockFromFile(filename$) // could be deleted, if Pattern-Notes are in new MemBlock apt_mod.error$="No error" MaxSamples = 31 apt_mod.modtype$=GetMemblockString(mem,1080,4) apt_mod.channels = 0 if apt_mod.modtype$="M.K." or apt_mod.modtype$="F.T." or apt_mod.modtype$="FLT4" apt_mod.channels = 4 elseif apt_mod.modtype$="6CHN" apt_mod.channels = 6 elseif apt_mod.modtype$="8CHN" or apt_mod.modtype$="FLT8" apt_mod.channels = 8 elseif GetMemblockString(mem,1082,2)="CH" // "28CH" xxCH not supported yet apt_mod.channels = Val(GetMemblockString(mem,1080,1))*10+Val(GetMemblockString(mem,1081,1)) else MaxSamples = 15 endif if apt_mod.channels <> 0 SetMemblockByte(mem,19,0) // to prevent String problems apt_mod.module_name$=GetMemblockString(mem,0,20) // 31 instruments following --- ~ line 332 from FMODDOC.TXT apt_mod.UniqueSamples = 0 sample_header_size = 30 for i=0 to MaxSamples-1 // 31 or 15 apt_mod.sample[i].sample_name$ = GetMemblockString(mem,20+i*sample_header_size,22) apt_mod.sample[i].sample_length = GetMemblockWord(mem,20+22+i*sample_header_size)*2 if apt_mod.sample[i].sample_length>0 inc apt_mod.UniqueSamples endif apt_mod.sample[i].fine_tune = GetMemblockByte(mem,20+22+2+i*sample_header_size) if apt_mod.sample[i].fine_tune>7 apt_mod.sample[i].fine_tune=apt_mod.sample[i].fine_tune-16 endif apt_mod.sample[i].volume = GetMemblockByte(mem,20+22+2+1+i*sample_header_size) apt_mod.sample[i].loop_start = GetMemblockWord(mem,25+i*sample_header_size)*2 apt_mod.sample[i].loop_length = GetMemblockWord(mem,27+i*sample_header_size)*2 next //--------------------- end of sample information ---------------- apt_mod.NumOrders=GetMemblockByte(mem,950) // SONG_LENGTH // 951 apt_mod.patternsbyte=GetMemblockByte(mem,951) maxpattern = GetMemblockByte(mem,952) for o=0 to 127 apt_mod.order[o]=GetMemblockByte(mem,952+o) if apt_mod.order[o]>maxpattern maxpattern = apt_mod.order[o] endif next apt_mod.NumPatterns = maxpattern+1 //--------------------------------------------------------------------------------------- // Calculation Memory for Patterns | from line 462 [2.6 Load Pattern Data] ... ~ 600] //--------------------------------------------------------------------------------------- // .MOD and S3M have 64 Notes at one pattern Size = (apt_mod.CHANNELS * 4 * 64) * apt_mod.NumPatterns // Size as Integer // Dword / LongInt apt_mod.padme = CreateMemblock(Size) CopyMemblock(mem,apt_mod.padme,1084,0,Size) // with 31 Instrument MOD else apt_mod.error$="Unsupported Format" endif EndFunction apt_mod //---------------------------------------------------------------- // note table global dim ntable [12] as String = ["C-","C#","D-","D#","E-","F-","F#","G-","G#","A","A#","B-"] Function StandardPrintOutput() // with Standard font withot loading fonts Print( "FPS: "+Left(Str(ScreenFPS(),2)+"00",5)+" .. Modul-Name: "+aptmod.module_name$) PrintC("Type: "+aptmod.modtype$+" .. NumOrders: "+Str(aptmod.NumOrders)+" .. Patterns: "+Str(aptmod.NumPatterns)+" .. UNUSED 127="+Str(aptmod.patternsbyte)+" .. ") Print("Channels: "+Str(aptmod.channels)+" .. ") Print("Error: "+aptmod.error$) PrintC("Orders:") For l=0 to aptmod.NumOrders-1 PrintC(" "+Str(aptmod.order[l])) Next Print("") Print("") Print("Unique Samples: "+Str(aptmod.UniqueSamples)) Print("") /* for k=0 to 14 PrintC(aptmod.sample[k*2 ].sample_name$+" -- ") Print(aptmod.sample[k*2+1].sample_name$+" -- ") next */ for k=0 to 30 Print(Right("0"+Str(k+1),2)+": "+aptmod.sample[k].sample_name$+" .. "+Str(aptmod.sample[k].sample_length)) next EndFunction Function AdvancedOutput() /* For j=0 to 15 FEN_TextXY(Str(j)+" TEXT",100,100+24*j,j) Next */ FEN_TextXY("Xaby's MOD-Player",5,0,15) //FEN_TextXY("----------------------",5,20,6) FEN_TextXY("Name:",265,0,10) FEN_TextXY(aptmod.module_name$,315,0,14) FEN_TextXY("Patterns:",540,0,10) FEN_TextXY(Str(aptmod.NumPatterns),622,0,7) FEN_TextXY("Orders:",655,0,10) FEN_TextXY(Str(aptmod.NumOrders),720,0,7) FEN_TextXY("Ch:"+Right("00"+Str(aptmod.channels),2),750,0,13) h=13 For m=0 to aptmod.NumOrders/22 s$ = " " For l=0 to 21 if m*22+l"+Right("00"+Str(aptmod.UniqueSamples),3)+" SAMPLES name < b.size",5,105,10) for k=0 to 30 FEN_TextXY(Right("00"+Str(k+1),3),1,120+k*h,7) FEN_TextXY(aptmod.sample[k].sample_name$,34,120+k*h,14) FEN_TextXY(Str(aptmod.sample[k].sample_length),238,120+k*h,7) //Right(+": "+aptmod.sample[k].sample_name$+" .. "+Str(aptmod.sample[k].sample_length)) next global fps_text_id, error_text_id fps_text_id=FEN_TextXY("FPS",165,0,13) error_text_id=FEN_TextXY("Error: "+aptmod.error$,0,580,15) //------------- Show Pattern -------------------- SetTextSize(FEN_TextXY("ROW CH-01 CH-02 CH-03 CH-04 | ----- ----- ----- ----- | Vol.>",310,105,10),20) for k=0 to 63 t=FEN_TextXY(Right("00"+Str(k+1),3),310,120+k*(h-6),7) SetTextSize(t,16) next EndFunction Function APT_MEMtoTXT(aptm as APT_MOD_File,filename$) b as Integer[4] fid=OpenToWrite(filename$) WriteLine(fid,"Songname: "+aptm.module_name$) for g=0 to aptm.numpatterns-1 WriteLine(fid,"Pattern: "+Right("00"+Str(g),3)) for q=0 to 63 WriteString(fid,Right("00"+Str(q),3)+": ") for d=0 to aptm.channels-1 // 4 Bytes [aaaaBBBB CCCCCCCCC DDDDeeee FFFFFFFFF] // aaaaDDDD = sample number // BBBBCCCCCCCC = sample period value // eeee = effect number // FFFFFFFF = effect parameters for z=0 to 3 b[z]=GetMemblockByte(aptm.padme,g*64+aptm.channels*q+4*d+z) next // %0001 << 1 -> %0010 //instrument = b[0]/16*16 + mod(b[2],16) SAMPLE_NUMBER = (b[0] AND 0xF0) + (b[2] >> 4) PERIOD_FREQUENZY = ((b[0] AND 0x0F) << 8) + b[1] EFFECT_NUMBER = b[2] AND 0x0F EFFECT_PARAMETER = b[3] WriteString(fid,Right("00"+Str(SAMPLE_NUMBER),3)+" "+Right("00"+Str(PERIOD_FREQUENZY),3)+" "+Right("00"+Str(EFFECT_NUMBER),3)+" "+Right("00"+Str(EFFECT_PARAMETER),3)+"|") //WriteString(fid,ntable[b[0]] next WriteLine(fid,"|") next next CloseFile(fid) EndFunction Init() global aptmod as APT_MOD_File //aptmod = Load_APT_MOD_File("4ma.mod") //aptmod = Load_APT_MOD_File("dyog.mod") //aptmod = Load_APT_MOD_File("dope.mod") // 28 Channels aptmod = Load_APT_MOD_File("deepness.mod") //aptmod = Load_APT_MOD_File("yaz_-_pandemonium.mod") //aptmod = Load_APT_MOD_File("veiled_sky.mod") //aptmod = Load_APT_MOD_File("frn_the_girl_2.mod") //aptmod = Load_APT_MOD_File("black_cat.mod") //aptmod = Load_APT_MOD_File("the_army_of.mod") //ogg=LoadMusicOGG("music.ogg") ogg=LoadSoundOGG("music.ogg") //PlaySound(ogg) mogg = CreateMemblockFromSound(ogg) CreateFileFromMemblock("music_wav_16Bit_44kHz.raw",mogg) AdvancedOutput() APT_MEMtoTXT(aptmod,"modastext.txt") do //StandardPrintOutput() // about 30% Frames better SetTextString(fps_text_id,"FPS: "+Left(Str(ScreenFPS(),2)+"00",5)) Sync() loop