![]() |
Forum Index : Microcontroller and PC projects : uM2(+): CFunctions
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Unfortunately the support site for CFunctions is no longer online so I have programmed a clunky but workable replacement for CFuncGen This is written in MMBasic V4.5 for DOS. Unfortunately this doesn't support OPTION EXPLICIT or INTEGER datatypes so some of the variable usage may be a bit unclear. However, I was impressed how reliable MMBasic for DOS is doing some quite complex logic. The program reads the .ELF file created by MPLabX and outputs the CFunctions in Basic format. There are simple instructions for use in the file header. If you can write CFunctions you should be able to work out how to use it, but any questions do ask. ![]() I used this document as my source of information on the .ELF file The program is tested on a selection of my CFunctions including display drivers and works properly on the tested examples but please let me know if you find any bugs. The program includes a fairly primitve mechanism for replacing Jump and Link instructions which are not position independent with Branch and link which are. This has only been tested with backwards references, e.g. calling the first function in a merged file from the second. 2015-09-06_134007_cfgen.zip ' ' CFGEN.BAS V1.0 ' ' Program to convert a .ELF file to Basic statements formatted for use as CFunctions ' Runs under MMBasic for DOS V4.5 ' ' It is recommended that the .ELF file is copied to the same directory as this file ' and that the filename is shortened to make life easier ' ' To run open a DOS box on the computer ' navigate to the directory containing the MMBasic.exe file and this program ' run MMBasic and you will get the normal ">" prompt ' Load this program ' Type run ' ' Then give the filename of the .elf file including the extension ' Choose "join" or "merge" to define the output format ' "join" is typically used for individual CFunctions, each function in the .ELF file is given ' its own header, all the CFunctions are output to a single file but can then be copied and ' pasted as required. When "join is chosen the "main" function is a dummy and is not included in the output ' "merge" is used for CFunctions such as drivers where one C function can be called from another ' ' Choose the name of the file for the Basic output. Do not include ".BAS", this will be appended automatically ' ' You can run MMBasic for DOS from MMEDIT, but in this case you will need to specify the correct directory information for the .ELF file ' dim program_header,section_header,program_header_size, program_header_num, section_header_size, section_header_num dim string_table_sector, string_table, text_section, text_position, text_size, text_link, symtab_section, strtab_section dim symtab_offset, symtab_num, symstr_offset, first dim text_add$ length 31 dim symbols$(100,2) length 31 line input ".ELF filename ? ",inname$ do line input "mode(join, merge) ? ",m$ loop while (m$<>"join") and (m$<>"merge") mode =0 if m$="merge" then mode=1 line input "CFunction name ? ",cname$ print "Created "+cname$+".bas" open cname$+".bas" for output as #2 first=1 'first time into the various loops print "processing ",inname$ open inname$ for random as #1 SEEK #1, 0 ' dat$ = INPUT$(16, #1) ' Get the .elf identification dat$=input$(12,#1) 'Get unused header dat$=input$(4,#1) program_header=getnum4(dat$) dat$=input$(4,#1) section_header=getnum4(dat$) dat$=input$(6,#1) 'step past the flags and header size dat$=input$(2,#1) program_header_size=getnum2(dat$) dat$=input$(2,#1) program_header_num=getnum2(dat$) dat$=input$(2,#1) section_header_size=getnum2(dat$) dat$=input$(2,#1) section_header_num=getnum2(dat$) dim sections$(section_header_num+2) dat$=input$(2,#1) string_table_sector=getnum2(dat$) ' i=section_header+ (Section_header_size*string_table_sector) + 16 'get to the offset in the string table sector seek #1,i dat$=input$(4,#1) string_table= getnum4(dat$) 'get the offset to the string table Print "Functions found:" print "Address",chr$(9)+"Function" for j=0 to section_header_num-1 i=section_header+ (Section_header_size*j) 'get to the next sector header seek #1,i 'point to the .text section header dat$=input$(4,#1) 'get the pointer to the sector name string k=getnum4(dat$) seek #1,k+string_table 'point to the name string for this sector s$="" d$=input$(1,#1) do while asc(d$)<>0 'read in the zero terminated string S$=S$+D$ d$=input$(1,#1) loop if s$=".text" and text_section=0 then 'store text sector number text_section=j endif if s$=".symtab" and symtab_section=0 then 'store symbol table sector number symtab_section=j endif if s$=".strtab" and strtab_section=0 then 'store symbol table strings sector number strtab_section=j endif next j ' i=section_header+ (Section_header_size*text_section) 'get to the .text offset seek #1,i 'point to the .text section header dat$=input$(12,#1) dat$=input$(4,#1) text_add$=getadd$(dat$) dat$=input$(4,#1) text_position=getnum4(dat$) dat$=input$(4,#1) text_size= getnum4(dat$) dat$=input$(4,#1) text_link= getnum4(dat$) dat$=input$(4,#1) text_info= getnum4(dat$) dat$=input$(4,#1) text_addralign= getnum4(dat$) dat$=input$(4,#1) text_entsize= getnum4(dat$) ' i=section_header+ 16+ (Section_header_size*(symtab_section)) seek #1,i 'point to the .text section header dat$=input$(4,#1) 'get the offset to the symbol table symtab_offset=getnum4(dat$) dat$=input$(4,#1) symtab_num=getnum4(dat$)/16 ' i=section_header+ 16+ (Section_header_size*(strtab_section)) seek #1,i 'point to the .text section header dat$=input$(4,#1) 'get the offset to the symbol table symstr_offset=getnum4(dat$) ' m=0 'counter for the stored symbols array for i=1 to symtab_num 'loop through all the symbols seek #1,symtab_offset+(16*i) 'point to the next symbol in the .symtab section dat$=input$(4,#1) k=getnum4(dat$) dat$=input$(4,#1) a$=getadd$(dat$) dat$=input$(4,#1) dat$=input$(1,#1) l=asc(dat$) seek #1,k+symstr_offset 'point to the symbol name s$="" d$=input$(1,#1) do while asc(d$)<>0 S$=S$+D$ d$=input$(1,#1) loop if l=18 and left$(s$,1)<>"_" then 'Only store function names symbols$(m,1)=a$ symbols$(m,2)=s$ print symbols$(m,1),symbols$(m,2) m=m+1 if s$="main" then main_offset$=a$ endif next i ' s$= hex$(subtract(right$(main_offset$,5),right$(text_add$,5))) 'calculate the offset of the main function if len(s$)=1 then s$="0000000"+S$ if len(s$)=2 then s$="000000"+S$ if len(s$)=3 then s$="00000"+S$ if len(s$)=4 then s$="0000"+S$ if len(s$)=5 then s$="000"+S$ if len(s$)=6 then s$="00"+S$ if len(s$)=7 then s$="0"+S$ main$=s$ ' seek #1,text_position k=0 currentfunction=0 s$=text_add$ for i=1 to text_size step 4 for j=0 to m-1 if s$=symbols$(j,1) then 'address matches the start of a function currentfunction=j if k<>0 and mode then print #2,"" 'The last function didn't end with a newline so output one if k<>0 and (not mode) and symbols$(j,2)<>"main" then print #2,"" k=0 if first and mode then ' First time in for a merged file output the Cfunction name print #2,"CFunction "+cname$ print #2,chr$(9)+main$ endif if mode then print #2,chr$(9)+"'"+symbols$(j,2) if not mode and symbols$(j,2)<>"main" then if not first then print #2,"End CFunction" print #2,"'" endif print #2,"CFunction "+symbols$(j,2) print #2,chr$(9)+"00000000" endif first=0 endif next j if k=0 then print #2,chr$(9); dat$=getadd$(input$(4,#1)) if left$(dat$,3)="0F4" then 'Jump instruction found convert to a branch a$=getjumpaddress$(right$(dat$,5)) 'this the address for the jump branchoffset=subtract(right$(s$,5),right$(a$,5)) branch$="0411FFFF" do decrement(branch$) branchoffset=branchoffset-1 loop while branchoffset if not mode and symbols$(currentfunction,2)<>"main" then print #2, branch$+" "; if mode then print #2, branch$+" "; else if not mode and symbols$(currentfunction,2)<>"main" then print #2, dat$+" "; if mode then print #2, dat$+" "; endif k=k+1 if k=8 then 'deal with line feed every eight words if not mode and symbols$(currentfunction,2)<>"main" then print #2,"" if mode then print #2,"" k=0 endif increment4(s$) 'step on the program counter next i if k<>0 then print #2,"" print #2,"End CFunction" close #1 close #2 ' end function subtract(b$,c$) local a,b,c,d,e,f,g,a$ a=asc(mid$(b$,5,1)) : a=a-48 : if a> 9 then a=a-7 b=asc(mid$(b$,4,1)) : b=b-48 : if b> 9 then b=b-7 c=asc(mid$(b$,3,1)) : c=c-48 : if c> 9 then c=c-7 d=asc(mid$(b$,2,1)) : d=d-48 : if d> 9 then d=d-7 e=asc(mid$(b$,1,1)) : e=e-48 : if e> 9 then e=e-7 f=((((((((e * 16) + d) * 16 ) + c ) * 16 ) + b ) * 16 ) + a) a=asc(mid$(c$,5,1)) : a=a-48 : if a> 9 then a=a-7 b=asc(mid$(c$,4,1)) : b=b-48 : if b> 9 then b=b-7 c=asc(mid$(c$,3,1)) : c=c-48 : if c> 9 then c=c-7 d=asc(mid$(c$,2,1)) : d=d-48 : if d> 9 then d=d-7 e=asc(mid$(c$,1,1)) : e=e-48 : if e> 9 then e=e-7 g=((((((((e * 16) + d) * 16 ) + c ) * 16 ) + b ) * 16 ) + a) subtract=(f-g)/4 end function function getjumpaddress$(a$) local a,b,c,d,e,f a=asc(mid$(a$,5,1)) : a=a-48 : if a> 9 then a=a-7 b=asc(mid$(a$,4,1)) : b=b-48 : if b> 9 then b=b-7 c=asc(mid$(a$,3,1)) : c=c-48 : if c> 9 then c=c-7 d=asc(mid$(a$,2,1)) : d=d-48 : if d> 9 then d=d-7 e=asc(mid$(a$,1,1)) : e=e-48 : if e> 9 then e=e-7 f=((((((((e * 16) + d) * 16 ) + c ) * 16 ) + b ) * 16 ) + a)*4 + 1048576 getjumpaddress$=left$(text_add$,3)+right$(hex$(f),5) end function function getadd$(d$) local a,b,c,d a=asc(left$(d$,1))+256 b=asc(mid$(d$,2,1))+256 c=asc(mid$(d$,3,1))+256 d=asc(right$(d$,1))+256 getadd$=right$(hex$(d),2)+right$(hex$(c),2)+right$(hex$(b),2)+right$(hex$(a),2) end function function getnum4(d$) local a,b,c,d a=asc(left$(d$,1)) b=asc(mid$(d$,2,1)) c=asc(mid$(d$,3,1)) d=asc(right$(d$,1)) getnum4=((((d*256)+c)*256)+b)*256+a end function function getnum2(d$) local a,b a=asc(left$(d$,1)) b=asc(right$(d$,1)) getnum2=b*256+a end function sub increment4(p$) local a,b,c,d,e,f,g,h,v a=asc(mid$(p$,8,1)) : a=a-48 : if a> 9 then a=a-7 b=asc(mid$(p$,7,1)) : b=b-48 : if b> 9 then b=b-7 c=asc(mid$(p$,6,1)) : c=c-48 : if c> 9 then c=c-7 d=asc(mid$(p$,5,1)) : d=d-48 : if d> 9 then d=d-7 e=asc(mid$(p$,4,1)) : e=e-48 : if e> 9 then e=e-7 f=asc(mid$(p$,3,1)) : f=f-48 : if f> 9 then f=f-7 g=asc(mid$(p$,2,1)) : g=g-48 : if g> 9 then g=g-7 h=asc(mid$(p$,1,1)) : h=h-48 : if h> 9 then h=h-7 a=a+4 : if a=16 then b=b+1 : a=0 if b=16 then c=c+1 : b=0: if c=16 then d=d+1 : c=0: if d=16 then e=e+1 : d=0 : if e=16 then f=f+1 : e=0 : if f=16 then g=g+1: f=0 : if g=16 then g=0: h=h+1 endif endif endif endif endif endif endif endif a=a+48: if a> 57 then a=a+ 7 b=b+48: if b> 57 then b=b+ 7 c=c+48: if c> 57 then c=c+ 7 d=d+48: if d> 57 then d=d+ 7 e=e+48: if e> 57 then e=e+ 7 f=f+48: if f> 57 then f=f+ 7 g=g+48: if g> 57 then g=g+ 7 h=h+48: if h> 57 then h=h+ 7 p$=chr$(h)+chr$(g)+chr$(f)+chr$(e)+chr$(d)+chr$(c)+chr$(b)+chr$(a) end sub sub decrement(p$) local a,b,c,d,e,f,g,h a=asc(mid$(p$,8,1)) : a=a-48 : if a> 9 then a=a-7 b=asc(mid$(p$,7,1)) : b=b-48 : if b> 9 then b=b-7 c=asc(mid$(p$,6,1)) : c=c-48 : if c> 9 then c=c-7 d=asc(mid$(p$,5,1)) : d=d-48 : if d> 9 then d=d-7 if a<>0 then a=a-1 else a=15 if b<>0 then b=b-1 else b=15 if c<>0 then c=c-1 else c=15 if d<>0 then d=d-1 else d=15 endif endif endif endif a=a+48: if a> 57 then a=a+ 7 b=b+48: if b> 57 then b=b+ 7 c=c+48: if c> 57 then c=c+ 7 d=d+48: if d> 57 then d=d+ 7 p$=left$(p$,4)+chr$(d)+chr$(c)+chr$(b)+chr$(a) end sub |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
I've never played with MMBASIC for DOS. Does it compile it's code to an exe or something like that you can run from the DOS command prompt? Smoke makes things work. When the smoke gets out, it stops! |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
It just runs the interpreter in a DOS box. The language is basically the same as Maximite less the various PIC specific hardware support. What makes it very useful for me is that the file handling is really easy just like on the Maximite. Because you can't do 32-bit integer arithmetic when you only have floats I've had to do some very inefficient coding with addresses maintained as 8 character hex strings but despite this the code runs perfectly acceptably quickly. If you need to do any sort of simple file format conversion and, like me, don't know things like python then MMBasic for Dos is a great solution. MMBasic for DOS is available here |
||||
paceman Guru ![]() Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
One of the very handy things that MMBasic for DOS has is the SYSTEM command. Format: SYSTEM command$
Useage: Submit 'command$' to the operating system. It can be any command recognised by the command window in Windows XP/Vista/7. The available commands are listed here: http://ss64.com/nt For example, this will set the window to blue lettering on a yellow background: SYSTEM "COLOR 1E" Note that the command is executed in a different instance of the command processor to MMBasic so some commands (like "CD ..") will have no effect. SYSTEM allows you to use Windows system commends for a range of things - it's particularly useful for multiple file handling. You can do things like: ProcessFolder:
'Create a DOS "DIR" command to list .txt files from the folder and re-direct 'the output .txt file list (filenames only) to a temporary data file "songlist.dat". SYSTEM "DIR *.txt /B/O:N >songlist.dat" 'MS Windows comand Songlist$ = Source$ + "songlist.dat" 'Build full filePath for songlist.dat 'Request file no. to process. Add folder path, process, then request next file. . . . Also you can build batch files to be executed, like: 'Read lyrics.txt file via lyricline$ variable into lyric$ array & count lines
FileLines = 0 Open FileName$ for input as #2 Do Line Input #2, lyricLine$ FileLines = FileLines + 1 lyric$(FileLines) = LyricLine$ Print "Line" filelines,lyric$(filelines) Loop Until filelines = 12 'EOF(#2) shortened for testing******** Close #2 'Identify music codec file type via batch file & read music file name from Filename.txt ' *** add other music file types (aac, org etc) later *** NameNoExt$ = left$(Filename$,len(Filename$)-4) Open "FileName.bat" for Output as #2 Print #2, "If Exist "+chr$(34)+NameNoExt$+".mp3"+chr$(34)+" echo "+NameNoExt$+".mp3> Filename.txt" Print #2, "If Exist "+chr$(34)+NameNoExt$+".m4a"+chr$(34)+" echo "+NameNoExt$+".m4a> Filename.txt" Close #2 SYSTEM "FileName.bat > nul" 'Batch command file creates Filename.txt which Open "FileName.txt" for Input as #2 'contains the music codec filename; if one exists. Line Input #2, MusicFile$ 'Now can read music codec filename with extension. Close #2 KILL "FileName.bat" KILL "FileName.txt" 'Setup batch file to start iTunes playing 'OutputString$ command format: ...START "" "MusicFile$"... 'The "" is apparently necessary & normally encloses the window title. Open "StartItunes.bat" for OUTPUT as #2 OutputString$ = "START "+chr$(34)+chr$(34)+" "+chr$(34)+MusicFile$+chr$(34) Print #2, OutputString$ Print #2, "Exit" Close #2 SYSTEM "StartItunes.bat > nul" 'Start the song playing Kill "StartItunes.bat" 'Delete temporary file 'Note: We have to "mouse-click" back into the MMBasic DOS window after the song is started, before 'timestamping can commence. . . . Greg |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Greg Very useful - thanks. Is there a way of getting MMBasic to accept parameters on the command line? e.g. MMBASIC cfgen.bas /f=test.elf /merge /o=myfile.bas |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
I have optimized the increment4 subroutine a bit. [code] sub increment4(value$) Local V$(7) LENGTH 1, i, NewValue$ LENGTH 8 for i= 0 to 7: V$(i) = mid$(value$, i+1, 1): next V$(7) = Chr$(Asc(V$(7)) + 4) for i = 7 to 1 step -1 v = Asc(V$(i)) if v > 70 then ' "F" V$(i) = Chr$(v - 23): V$(i-1) = Chr$(Asc(V$(i-1)) + 1) else if v >57 and v < 65 then V$(i) = Chr$(v + 7) ' "9" "A" endif NewValue$ = V$(i)+ NewValue$ next value$ = V$(0) + NewValue$ end sub [/code] Also you can use the VAL function to get the value of a HEX character so instead of doing: [code] a=asc(mid$(a$,5,1)) : a=a-48 : if a> 9 then a=a-7 [/code] you can do: [code] a = val("&H" + mid$(a$,5,1)) [/code] Alternatieve for: [code] s$= hex$(subtract(right$(main_offset$,5),right$(text_add$,5))) 'calculate the offset of the main function if len(s$)=1 then s$="0000000"+S$ if len(s$)=2 then s$="000000"+S$ if len(s$)=3 then s$="00000"+S$ if len(s$)=4 then s$="0000"+S$ if len(s$)=5 then s$="000"+S$ if len(s$)=6 then s$="00"+S$ if len(s$)=7 then s$="0"+S$ main$=s$ [/code] is [code] main$= right$("00000000"+hex$(subtract(right$(main_offset$,5),right$(text_add$,5))),8) 'calculate the offset [/code] Still working on the decrement sub.:) Microblocks. Build with logic. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
TZ Great stuff ![]() You will see the decrement routine is actually used in a loop to subtract two addresses so what is really needed is a routine that subtracts "12AB34CD" from "34CD12AB" Thanks Peter |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Sort of... MMBasic.ex will take a BAS file name on the commandline but that's all I used this cludge to get a command line string to a BAS program All it does is get your BAS program to read a known configuration/command line file. Batch file: echo. "more command line stuff" > temp.txt
"C:\Users\Jim\Documents\apps\maximite\DOS MMBasic\MMBasic.exe" test.bas TEST.BAS print "Welcome"
print mm.cmdline$ open "C:\Users\Jim\Documents\apps\maximite\DOS MMBasic\temp.txt" for input as #1 input #1, myfile$ close #1 print myfile$ print "Done" You will need to edit the paths in both files. Jim VK7JH MMedit |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Thanks to TZ I've improved all the calculation algorithms, unfortunately it doesn't make things much faster as most of the time is spent file positioning but it certainly looks cleaner. ' ' CFGEN.BAS V1.1 ' V1.1 Improved algorithms thanks to TZ ' V1.11 Tidy Up ' ' Program to convert a .ELF file to Basic statements formated for use as CFunctions ' Runs under MMBasic for DOS V4.5 ' ' It is recommended that the .ELF file is copied to the same directory as this file ' and that the filename is shortened to make life easier ' ' To run open a DOS box on the computer ' navigate to the directory containing the MMBasic.exe file and this program ' run MMBasic and you will get the normal ">" prompt ' Load this program ' Type run ' ' Then give the filename of the .elf file including the extension ' Choose "join" or "merge" to define the output format ' "join" is typically used for individual CFunctions, each function in the .ELF file is given ' its own header, all the CFunctions are output to a single file but can then be copied and ' pasted as required. When "join is chosen the "main" function is a dummy and is not included in the output ' "merge" is used for CFunctions such as drivers where one C function can be called from another ' ' Choose the name of the file for the Basic output. Do not include ".BAS", this will be appended automatically ' ' You can run MMBasic for DOS from MMEDIT, but in this case you will need to specify the correct directory information for the .ELF file ' dim section_header, section_header_size, section_header_num dim string_table_sector, string_table, text_section, text_position, text_size, text_link, symtab_section, strtab_section dim symtab_offset, symtab_num, symstr_offset, first dim text_add$ length 31 dim symbols$(100,2) length 31 line input ".ELF filename ? ",inname$ do line input "mode(join, merge) ? ",m$ loop while (m$<>"join") and (m$<>"merge") mode =0 if m$="merge" then mode=1 line input "CFunction name ? ",cname$ print "Created "+cname$+".bas" open cname$+".bas" for output as #2 PRINT #2,"'File "+cname$+".bas written "+DATE$+" "+Time$ first=1 'first time into the various loops print "processing ",inname$ open inname$ for random as #1 SEEK #1, 0 ' dat$ = INPUT$(32, #1) ' Get the .elf identification and unused header dat$=input$(4,#1) section_header=getnum4(dat$) dat$=input$(10,#1) 'step past the flags ,header size, and program header info dat$=input$(2,#1) section_header_size=getnum2(dat$) dat$=input$(2,#1) section_header_num=getnum2(dat$) dat$=input$(2,#1) string_table_sector=getnum2(dat$) ' i=section_header+ (Section_header_size*string_table_sector) + 16 'get to the offset in the string table sector seek #1,i dat$=input$(4,#1) string_table= getnum4(dat$) 'get the offset to the string table Print "Functions found:" print "Address",chr$(9)+"Function" for j=0 to section_header_num-1 i=section_header+ (Section_header_size*j) 'get to the next sector header seek #1,i 'point to the .text section header dat$=input$(4,#1) 'get the pointer to the sector name string k=getnum4(dat$) seek #1,k+string_table 'point to the name string for this sector s$="" d$=input$(1,#1) do while asc(d$)<>0 'read in the zero terminated string S$=S$+D$ d$=input$(1,#1) loop if s$=".text" and text_section=0 then 'store text sector number text_section=j endif if s$=".symtab" and symtab_section=0 then 'store symbol table sector number symtab_section=j endif if s$=".strtab" and strtab_section=0 then 'store symbol table strings sector number strtab_section=j endif next j ' i=section_header+ (Section_header_size*text_section) 'get to the .text offset seek #1,i 'point to the .text section header dat$=input$(12,#1) dat$=input$(4,#1) text_add$=getadd$(dat$) dat$=input$(4,#1) text_position=getnum4(dat$) dat$=input$(4,#1) text_size= getnum4(dat$) dat$=input$(4,#1) text_link= getnum4(dat$) ' i=section_header+ 16+ (Section_header_size*(symtab_section)) seek #1,i 'point to the symbol table section header dat$=input$(4,#1) 'get the offset to the symbol table symtab_offset=getnum4(dat$) dat$=input$(4,#1) symtab_num=getnum4(dat$)/16 ' i=section_header+ 16+ (Section_header_size*(strtab_section)) seek #1,i 'point to the string table section header dat$=input$(4,#1) 'get the offset to the symbol table symstr_offset=getnum4(dat$) ' m=0 'counter for the stored symbols array for i=1 to symtab_num 'loop through all the symbols seek #1,symtab_offset+(16*i) 'point to the next symbol in the .symtab section dat$=input$(4,#1) k=getnum4(dat$) dat$=input$(4,#1) a$=getadd$(dat$) dat$=input$(4,#1) dat$=input$(1,#1) l=asc(dat$) seek #1,k+symstr_offset 'point to the symbol name s$="" d$=input$(1,#1) do while asc(d$)<>0 S$=S$+D$ d$=input$(1,#1) loop if l=18 and left$(s$,1)<>"_" then 'Only store function names symbols$(m,1)=a$ symbols$(m,2)=s$ print symbols$(m,1),symbols$(m,2) m=m+1 if s$="main" then main_offset$=a$ endif next i ' main$= right$("00000000" + hex$(subtract(right$(main_offset$,5), right$(text_add$,5))), 8) 'calculate the offset ' seek #1,text_position k=0 currentfunction=0 s$=text_add$ for i=1 to text_size step 4 for j=0 to m-1 if s$=symbols$(j,1) then 'address matches the start of a function currentfunction=j if k<>0 and mode then print #2,"" 'The last function didn't end with a newline so output one if k<>0 and (not mode) and symbols$(j,2)<>"main" then print #2,"" k=0 if first and mode then ' First time in for a merged file output the Cfunction name print #2,"CFunction "+cname$ print #2,chr$(9)+main$ endif if mode then print #2,chr$(9)+"'"+symbols$(j,2) if not mode and symbols$(j,2)<>"main" then if not first then print #2,"End CFunction" print #2,"'" endif print #2,"CFunction "+symbols$(j,2) print #2,chr$(9)+"00000000" endif first=0 endif next j if k=0 then print #2,chr$(9); dat$=getadd$(input$(4,#1)) if left$(dat$,3)="0F4" then 'Jump instruction found convert to a branch a$=getjumpaddress$(right$(dat$,5)) 'this the address for the jump branchoffset=subtract(right$(s$,5),right$(a$,5)) branch$=subaddress$("0411FFFF",branchoffset) if not mode and symbols$(currentfunction,2)<>"main" then print #2, branch$+" "; if mode then print #2, branch$+" "; else if not mode and symbols$(currentfunction,2)<>"main" then print #2, dat$+" "; if mode then print #2, dat$+" "; endif k=k+1 if k=8 then 'deal with line feed every eight words if not mode and symbols$(currentfunction,2)<>"main" then print #2,"" if mode then print #2,"" k=0 endif increment4(s$) 'step on the program counter next i if k<>0 then print #2,"" print #2,"End CFunction" close #1 close #2 ' end function subtract(b$,c$) local f,g f=val("&H"+b$) g=VAL("&H"+c$) subtract=(f-g)/4 end function function getjumpaddress$(a$) local f f=VAL("&H"+a$)*4+1048576 getjumpaddress$=left$(text_add$,3)+right$(hex$(f),5) end function function getadd$(d$) local a,b,c,d a=asc(left$(d$,1))+256 b=asc(mid$(d$,2,1))+256 c=asc(mid$(d$,3,1))+256 d=asc(right$(d$,1))+256 getadd$=right$(hex$(d),2) +right$(hex$(c),2) +right$(hex$(b),2) +right$(hex$(a),2) end function function getnum4(d$) local a,b,c,d a=asc(left$(d$,1)) b=asc(mid$(d$,2,1)) c=asc(mid$(d$,3,1)) d=asc(right$(d$,1)) getnum4=((((d*256)+c)*256)+b)*256+a end function function getnum2(d$) local a,b a=asc(left$(d$,1)) b=asc(right$(d$,1)) getnum2=b*256+a end function sub increment4(value$) Local V$(7) LENGTH 1, i, NewValue$ LENGTH 8 for i= 0 to 7: V$(i) = mid$(value$, i+1, 1): next V$(7) = Chr$(Asc(V$(7)) + 4) for i = 7 to 1 step -1 v = Asc(V$(i)) if v > 70 then ' "F" V$(i) = Chr$(v - 23): V$(i-1) = Chr$(Asc(V$(i-1)) + 1) else if v >57 and v < 65 then V$(i) = Chr$(v + 7) ' "9" "A" endif NewValue$ = V$(i)+ NewValue$ next value$ = V$(0) + NewValue$ end sub function subaddress$(p$,b) local a a=val("&H"+RIGHT$(p$,4))+65536-b subaddress$=left$(p$,4)+right$(hex$(a),4) end function |
||||
disco4now![]() Guru ![]() Joined: 18/12/2014 Location: AustraliaPosts: 1003 |
Hi Peter, Thanks for replacement CFunctGen. I have used your first posted version in anger and have successfully called DrawPixel using the MMBasic API. I found it quite convenient to use via MMBasic, just run up a second copy of MMBasic and loaded CFunctGen.bas , remark out the prompts and hard code your file names etc and save a copy with the project name appended. This makes it easy to run multiple times as you do in development. A good way to get long windows directory + file names into the clipboard is to open up the run dialogue and then drag the file to the input field. You can then get it from there into the clipboard and paste where you want. ![]() So after being away for a couple of months away I am nearly caught up. The C code below shows calling the DrawPixel routine in MMbasic from C via the MMbasic API. /*
* File: newmain.c * Author: gallardice * * Created on 6 September 2015, 8:43 PM */ #define _SUPPRESS_PLIB_WARNING #include <plib.h> #define FAM #include "APIDefs.h" #define DEVID (*(volatile unsigned int *)0xBF80F220) #define PIC32MX170F256B_DEVID 0x06610053 #define PIC32MX270F256B_DEVID 0x06600053 #define PIC32MX170F256D_DEVID 0x0661A053 #define PIC32MX270F256D_DEVID 0x0660A053 #define HAS_28PINS ((DEVID & 0xfffffff) == PIC32MX170F256B_DEVID || (DEVID & 0xfffffff) == PIC32MX270F256B_DEVID) long long drawPixel(long long *xp,long long *yp,long long *cp){ int x=*xp,y=*yp,c=*cp; DrawPixel(x,y,c); return(0); } //We need a main to keep the compiler happy void main(){} This is the CFunction generated by Peters program CFunction drawPixel 00000000 27BDFFE0 AFBF001C 8C830000 8CA70000 3C029D00 8C420048 8CC40000 AFA40010 8C420000 00602021 00E02821 0040F809 00603021 00001021 00001821 8FBF001C 03E00008 27BD0020 End CFunction Here is a snippet from MMBasic showing a loop writing two parrallel lines, one via MMBasic command PIXEL and the other calling the CFunction drawPixel() which then calls the MMBasic binary via its API entry point DrawPixel. dim result AS INTEGER
for I%=10 to 240 STEP 1 PIXEL I%-5,I%, RGB(green) 'MMBasic result=drawPixel(I%,I%,RGB(red)) 'CFunction NEXT I% Thanks again Peter for all the good stuff. Regards Gerry Latest F4 Latest H7 FotS |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Can someone send me an ELF file AND the created output file. I want to test something and having a working example will greatly simply testing it. Microblocks. Build with logic. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Here you go: 2015-09-07_135511_ILI9325.zip I use winmerge to check each modification doesn't compromise the output |
||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2442 |
does anybody know what happened to the support site for CFunctions? is it down temporarily? cheers, rob :-) |
||||
paceman Guru ![]() Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Not directly as I remember. Jim's method obviously works - the one in the middle box I posted above works well too but it's read from a batch file and called from the MMBasic program with SYSTEM. For your development work, maybe a macro from MMEdit or TT could be used? |
||||
twofingers![]() Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1593 |
Thanks Peter! ![]() Good job. I think I have never seen a (functional) program for MMBasic for DOS. I assumed it was just for testing purposes ... I hope Peter C. (G8JCF) is doing well! ![]() Michael causality ≠ correlation ≠ coincidence |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Peter, I have been playing with your cfungen program and converting it to a windows application. So far I can agree with the example you provided. I do need to tidy up the user interface before I let you play with it. I did find one bug. I think FOR i=1 TO symtab_num 'loop through all the symbols
should be FOR i=0 TO symtab_num-1 'loop through all the symbols
As it stands your code ends up seeking beyond the end of the file. I added a test IF i >(symtab_num -2) THEN
PRINT "Woops! ",FORMAT$(k+symstr_offset, "%9.0f"),filesize ENDIF SEEK #1,k+symstr_offset 'point to the symbol name and the resulting printout: Woops! 184744 184755
Woops! 1651246464 184755 The first time the test is triggered, seek position is less than the file size but the second time, we are well over the file size. MMBasic didn't throw an error but my PureBasic certainly did. Jim VK7JH MMedit |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Excellent news. I've managed to spend an entire career in IT without ever having to do windows I/F work so your contribution will be greatly appreciated. Good catch, anyone using my code, please make the change. |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Gui programming can be a pain, especially when Microsoft keep changing things. I found a bug in MMEdit where it was not starting DOS basic in the correct folder. It will be fixed in the next release. Here is my attempt at CFUNCTION generator. It has only been tested with the one ELF file so beware.... Usage: select the ELF file Select the destination file (if you cancel, you can do a dummy run) Choose Merge or Join. The result is printed to the text window and saved to your chosen destination. I will add a few more sanity checks but I want to know that it works first. 2015-09-09_085634_cfgen.zip Jim VK7JH MMedit |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Jim First look, the live window looks OK but the file produced has the first value on the same line as the CFunction in join mode e.g. CFunction npins 00000000
3C02BF81 8C44F220 7C84D800 3C030661 3463A053 1083000B 2402002C 3C02BF81 8C43F220 7C63D800 3C020660 3442A053 00621026 2403001C 2404002C 0082180A 00601021 3C03BF81 8C64F220 7C84D800 3C030580 3463A053 00832026 24030040 0064100A 3C03BF81 8C64F220 7C84D800 3C030580 3463B053 00832026 24030064 0064100A 03E00008 00021FC3 End CFunction Also, can you put a time and date in the file as a comment - I did this in my current version. Finally, please could you arrange that pressing join or merge will cause the file to be regenerated each time they are pressed by re-reading the source. This will allow the program to be left open and just press the button each time you want to update after a new .ELF is produced |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Fixed the layout problem with the file output - typo. Added date as comment. You can now rerun with the same file names as often as desired using 'Join' and 'Merge' 'New' lets you re-select the files. As well as outputting to a file, the output is copied to the clipboard ready for pasting into a program. Is there any call for the ability to read a commandline? 2015-09-10_002014_cfgen.zip Jim VK7JH MMedit |
||||
Page 1 of 2 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |