;From Graham Medland ; gm236@ex.ac.uk or dakoder@yahoo.com ; www.dakoder.co.uk/x86 ; ;If you find this code usefull or have any questions It would be great to hear from you. ; ; ;Target assembler A386.COM see www.eji.com ;this code expects to be in protected 32 bit mode use32 ;each page points to a new 64k block so page 2=128k from cs:00000000 ; Memory Map of usage ; UPPERCASE = offset pointer, if offset from zero then becomes physiacl ; lowercase = physical address ;address address size ; ;00200000 2meg 12meg ;the hex ascii file shrinkit ;00100000 1meg 512k ;picmem opcodes word sized ;00020000 128k 28k ;van2 text area eeprom ;00010000 64k 3k ;vscreen ;00000100 64k ;code entry ;00000080 128 ;DTA ;???????? ;stack area still resides in v86 memory ! pic_mem equ 0100000 ; page 010 ds:01meg = start address of pic opcode data, leaves 1 meg of room fuses equ pic_mem-2 ; fuses are -2 from 0000 CLIBUFF equ 0200000 ; where the shrinkit hex was but is now cleared BPXMEM equ 0180000 ; 512k offset from pic_mem PICMEM equ 0100000 ; offset of 1 meg for hex data file. physical address = pic_mem + PICMEM XVAN5 equ 0B0000 ; 64k COD file area for DATA symbols only XVAN4 equ 0A0000 ; 64k COD file area for CODE symbols only XVAN3 equ 080000 ; code & file window XVAN2 equ 040000 ; eprom window where the van2 text box is stored VSCREEN equ 010000 ; where the screen is drawn, then rip of the sections you need and paint to vga org 0100 ; yes a 32 bit pmode com file oooohhh ! ; 76543210 ;turbo -------- this is the system flags ; bit 0 0 = scan keyboard for break out (slow mode) ; 1 = do not scan keyboard (fast mode) ; ; ; ; ; ; ; ; 5 0 = radix is HEX ; 1 = radix is DEC ; 6 0 = Lables to screen (yes we have colour) ; 1 = lables to dump (No colours) jmp entry ; skip the data sel_code: dw 0 sel_data: dw 0 ; data32 (4 gig) base address = CS sel_flat: dw 0 ; FLAT sel_b800: dw 0 ; FS = VGA sel_a000: dw 0 ; GS = VGA optv86: dd 0 ; EAX = linear address of original v86 code optcs: dd 0 ; EBX = linear address of CS eyedata: dd 0 ; vector address of variable dd 0 ; the value of the variable db 0 ; size of variable (dest) codfile: db 0 ; 0 = NOT loaded, 1= loaded db 0 dup(0ff) ; MPASM, DATE, TARGET PIC, tmr_ticks: dd 0 temp: dd 0,0 ; temp storage for stack when doing hotkeys. turbo: db 040 ; system control flag (see above) cursor: dw 0 ; x,y of cursor pos on vga screen, also used as a pointer to within windowtext box colour1: db 02 ; colour of green line db 0c ; bpx marker db 0f ; cli text db 07 ; default screen colour db 0f6 ; special colour of labels, the f=insert colour and 6 is the the colour twf: db 0 ; toggle window flag, 0 = 1 column : 1 = 2 column godoit: dd 0 ; this is the execute address stage: db 0 ; 0 = start off, 1 = comand found 2 = pars 3 ascii: db 0ff,1 ; mask for high byte of strings in program memory., mask for the low byte <32 or >127 = dot vscr_ww: dd 0,0 ; where in the VSCREEN the watch window address is , how many bytes vscr_ew: dd 0,0 ; where in the VSCREEN the eprom window address is vscr_sp: dd 0,0 ; where the stack pointer is vscr_st: dd 0,0 ; where the status window is cli_top: dd 0 ; address of top of cli screen (first byte to be printed) dw 0 ; line counter. cli_top = this word*80 greenln: db 0 ;special green line counter for adjusting the number of lines left on the screen for CLIBUFF kbuf0: db 80 dup 0 ;pointer + search string buffer db 80 dup 0 ;duplicate string for F3 hotkey kbufz: dd 0 ;length of string so ok can be placed bluetext: db " " db " Enter a command or type 'help' or 'hotkey' to get started " db " No such command. " db " Press SPACE BAR to move on, press ESC to break this loop " int_var_heap: db "codfile",1 dd codfile db "SICEbpx",4 dd command1 ;our breakpoint db "sel_code",2 dd sel_code db "sel_data",2 dd sel_data db "sel_flat",2 dd sel_flat db "sel_b800",2 dd sel_b800 db "sel_a000",2 dd sel_a000 db "linear_v86",4 dd optv86 db "linear_code",4 dd optcs db "eyedata",4 dd eyedata db "tmr_ticks",4 dd tmr_ticks db "turbo",1 dd turbo db "cursor",2 dd cursor db "colour1",4 dd colour1 db "twf",1 dd twf db "stage",1 dd stage db "ascii",2 dd ascii db "vscr_ww",4 dd vscr_ww db "vscr_ew",4 dd vscr_ew db "vscr_sp",4 dd vscr_sp db "vscr_st",4 dd vscr_st db "cli_top",4 dd cli_top db "kbufz",4 dd kbufz db 0 ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;the help and command data section ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ; ": designates start of command string (10 chars long max) ; ,1, marks the end of the command and the start of the description of the command ; ,2, marks the start of the description of command line pars ; ,3 marks the start of the example useage string ; ,4 marks the start if the detailed help string ; ,5 marks the end of the detailed help string ; dd is the 32 bit offset address where routine is executed ; ,0, termination of command heap data ; command: ; -------------------------------------------------------------------------------- ;db ":? ",1, "ў evaluate expression",2 ;db "see instruction book",3 ;db "see instruction book",4 ;db "used as complex calculator and base conversion etc",5 ;dd do_nothing db ":ver ",1, " ў Get the current version number and registration details",2 db " ",3 db "eg [ ver ]$$",4 db "Gives details about which version you are running.$The serial number is comprised of date,status and revision number$$",5 dd do_about ;db ":bpe ",1, " ў set a Break Point on Eprom memory address",2 ;db "[ address ]",3 ;db "[ bpe 023 ] [ bpe 00100011 ]",4 ;db "Free run execution of code stops when the specified eeprom address is accessed",5 ;dd do_bpe db ":bpl ",1, " ў Break Point List. Gives a list of all BreakPoints set",2 db " ў Break Point List. Gives a list of all BreakPoints set",3 db "eg [ bpl ]$$",4 db "Gives a complete list of all addresses that contain a sticky BreakPoint$BreakPoints are identified by '' symbol in the Code Window$$",5 dd do_bpl db ":bpx ",1, " ў Create / remove (toggle) a sticky Break Point on ip eXecute address",2 db "[ address ]",3 db "eg [ bpx 0 ] [ bpx 04 ] [ bpx 027f ]$$",4 db "Creates / Removes (toggles) a sticky BreakPoint at the address specified.$All sticky BreakPoints are identified by '' symbol in the Code Window$$",5 dd do_bpx db ":cls ",1, " ў CLear the Screen",2 db " ў CLear the Screen",3 db "eg [ cls ]$$",4 db "Clears the command text entry screen and nothing else$$",5 dd do_cls db ":cw ",1, " ў Code Window on (and/or) set displayed lines",2 db "[ number of lines ]",3 db "eg [ cw ] [ cw 16 ] [cw 010 ]$$",4 db "Switches the secondary code window on.$You can also specify the number of lines to use.$Changing the size of the code window also changes the size of the file window$$",5 dd do_codewin db ":dump ",1, " ў DUMP program/file registers and eeprom data to disk as a text file",2 db " ў DUMP program/file registers and eeprom data to disk as a text file",3 db "eg [ dump ]$$",4 db "This creates a huge text file containing everything you need$the disk filename created will be called PICDEBUG.LST and will be a standard$text file using cr/lf characters at the end of each line. The file will be$created in the same directory as the hex file you loaded and will overwrite$the old PICDEBUG.LST if one exists$$",5 dd do_dump ;db ":erase ",1," ў ERASE flash memory of pic",2 ;db " ў ERASE flash memory of pic",3 ;db "[ erase ]",4 ;db "ERASEs the program / eeprom and config memmory of the pic to all 1's",5 ;dd do_nothing db ":ew ",1, " ў Eprom Window on/off or set displayed lines and turn on window",2 db "[ Number of lines ]",3 db "eg [ ew ] [ ew 16 ] [ew 010 ]$$",4 db "Switches the eprom window on/off $You can also specify the number of lines to use.$$",5 dd do_eprmwin db ":exit ",1, " ў exit from PICDEBUG session",2 db " ў exit from PICDEBUG session",3 db "eg [ exit ]$$",4 db "Exit from the program and takes you back to the DOS prompt$$",5 dd goodexit db ":fast ",1, " ў Enter turbo mode by switching keyboard off USE WITH CARE !",2 db " ў Enter turbo mode by switching keyboard off USE WITH CARE !",3 db "eg [ fast ]$$",4 db "Switches the keyboard OFF. This will allow upto 8 Mhz or 2 Mips on a 600M Hz$pentium with 10 ns SDRAM. You will be unable to press ESC to manualy BREAK$into FREE running CODE !!!!! use 'slow' to put keyboard back on again.$If you do end up doing this simply press CTRL-ALT-DEL once and then using the$Arrow keys select the MSDOS PROMPT and click END TASK. which will shut down$The program and return you to windows. See 'slow' for turning it on again$$",5 dd do_fast db ":fw ",1, " ў File register Window on (and/or) set displayed lines",2 db "[ Number of lines ]",3 db "eg [ fw ] [ fw 16 ] [fw 010]$$",4 db "Switches the file register window on.$You can also specify the number of lines to use.$Changing the size of the file window also changes the size of the code window$$",5 dd do_filewin db ":go ",1, " ў GO until (address / condition) is met or ESC is pressed. ",2 db "[ address ] ",3 db "eg [ go ] [ go 01ff ] [ go w=03c ] [ go fosc=1234 ] [ go eeadr=03f ]$$",4 db "Continue executing code from the current IP to the specified address$Execution will stop if a sticky BreakPoint is reached or you press ESCAPE$If no address is specified then a non-sticky one time only BreakPoint is set$at address minus 1$$",5 dd do_go db ":hotkey ",1," ў List all hotkeys ",2 db " ў List all hotkeys ",3 db "[ hotkey ]",4 db "Lists all the hotkeys that bypass the text entry screen",5 dd do_hotkeys db ":help ",1, " ў for general help / press space bar and type in command",2 db "[ command ]",3 db "eg [ help ] [ help dump ] [ help bpx ]$$",4 db "gives you general and specific help on commands and syntax.",5 dd do_help db ":jmp ",1, " ў JuMP to address specified, nothing is changed other than IP",2 db "[ address ]",3 db "eg [ jmp 0fff ] [ jmp 0100 ]$$",4 db "Just changes the current value of the IP to the specified address$$Note: The address limit is based on the internal size of each device which is$larger than the physical address space when running code.$This extra address space is where the configuration memory is held$If you jmp to the address 0404 on the 12c509a you can see the POST code$$",5 dd do_jmp ;db ":peekf ",1, " ў read contents of file register",2 ;db "[ address ]",3 ;db "[ peekf 0fe ] [ peekf _gpio ] [ peekf 71 ]",4 ;db "allows a quick look at the content of a file register",5 ;dd do_nothing ;db ":pokef ",1, " ў set contents of file register",2 ;db "[ address ] ['string' | value ]",3 ;db "[ pokef 0fe 10110111 ] [ pokef _gpio 0aa ] [ pokef 71 'a' ]",4 ;db "allows you to modify the contents of a particular file register",5 ;dd do_nothing ;db ":peekp ",1, " ў read contents of program memory",2 ;db "[ address ]",3 ;db "[ peekp 01ffe ] [ peekp _ip ] [ peekp 1024 ]",4 ;db "allows you to see embedded ascii code or id values within the program memory",5 ;dd do_nothing ;db ":pokep ",1, " ў set contents of program memory",2 ;db "[ address ] ['string' | value ]",3 ;db "[ pokep 01ffe 10110111 ] [ pokep _ip 0aa ] [ pokep 1024 'ascii' ]",4 ;db "allows you to put embedded ascii code or id values within the program memory",5 ;dd do_nothing db ":peek ",1, " ў Peek at the runtime DPMI information.",2 db "[ Peek ]",3 db "allows you to see the internal registers and settings of the 32 bit runtime ",4 db "code. eg. selectors / memory size etc ",5 dd do_peek ;db ":pret ",1, " ў procede until ret instruction reached",2 ;db " ",3 ;db "[ pret ]",4 ;db "continue execution until a RET, IRET or RETLW instruction is reached",5 ;dd do_nothing ;db ":pint ",1, " ў procede until interupt occurs",2 ;db " ",3 ;db "[ pint ]",4 ;db "continue execution until an interupt causes a break in the program flow",5 ;dd do_nothing ;db ":pcall ",1, " ў procede until call instruction reached",2 ;db " ",3 ;db "[ pcall ]",4 ;db "continue execution until a CALL instruction is reached",5 ;dd do_nothing ;db ":pjmp ",1, " ў procede until jump instruction reached ",2 ;db " ",3 ;db "[ pjmp ]",4 ;db "continue execution until a JMP or GOTO instruction is reached",5 ;dd do_nothing db ":p ",1, " ў none conditional Procede until IP + 1 is reached",2 db "[ Hotkey = F5",3 db "eg [ p ]$$",4 db "Set a non-sticky BreakPoint at IP+1 and execute the current instruction$$Note: If the instruction being executed changes the IP so that the non-sticky$breakpoint is not the next instruction, then execution will continue at the$modified address until it is reached (sticky BreakPoints apply)$hotkey: F5$$",5 dd do_msf5 db ":read ",1, " ў read contents of pic chip ",2 db " ў read contents of pic chip ",3 db "eg [ read ]$$",4 db "reads program, eeprom and configuration memmory of the pic and simulates a$power on reset ( POR ). All contents of the eprom are wiped and replaced$with that found in the PIC$$",5 dd readpic db ":rdx ",1, " ў toggle the RaDiX from HEX to DEC.",2 db " ў toggle the RaDiX from HEX to DEC.",3 db "eg [ rdx ]$$",4 db "Changes the default number base of certain variables from HEX to DEC$$",5 dd do_rdx db ":reset ",1, " ў reset the pic ",2 db " ў reset the pic ",3 db "eg [ reset ]$$",4 db "reset all registers simulates the power being switched off and back on again$$",5 dd do_reset db ":slow ",1, " ў Enter slow (normal) mode by switching keyboard on",2 db " ў Enter slow (normal) mode by switching keyboard on",3 db "eg [ slow ]$$",4 db "Switches the keyboard ON. This is the prefered mode of operation as it$enables you to break out of free running code by pressing ESCAPE$see 'fast' command$$",5 dd do_slow db ":style ",1," ў Toggle the STYLE of disassembled code, Micro-chip / Intel",2 db " ў Toggle the STYLE of disassembled code, Micro-chip / Intel",3 db "eg [ style ]$$",4 db "Switches between different forms of mnemonics in the disassembly.$Microchips specific code or x86 style mnemonics.$$",5 dd do_style db ":t ",1, " ў trace one instruction and follow program code",2 db "[ repeat ]",3 db "eg [ t ] [ t 20 ] [ t 0100 ]$$",4 db "Execute the current instruction(s) and follow normal program flow$$Note: Only one instruction is executed each time and all forms of BreakPoints$are ignored$hotkey: F1$$",5 dd do_trace db ":varl ",1, " ў VARiable List. Gives a list of all the PIC variables",2 db " ў VARiable List. Gives a list of all the PIC variables",3 db "eg [ varl ]$$",4 db "Gives a complete list of all the internal pic variables that are available$for use$$",5 dd do_varl db ":vars ",1, " ў VARiable Set. Change the contents of a variable",2 db " ў [ value ] or [ variable ]",3 db "eg [ vars config=01ef ] [ vars w=eedata ]$$",4 db "Allows you to set any variable to any value or value of another variable$Use 'varl' to get a list of variables available.$$",5 dd do_vars db ":varh ",1, " ў VARiable Help. Gives Help on a particular PIC variable",2 db " ў VARiable Help. Gives Help on a particular PIC variable",3 db "eg [ varh status ] or [ varh config ]$$",4 db "Gives a complete breakdown of the specified register$$$",5 dd do_varh ;db ":we ",1, " ў set up an eeprom memory watch window",2 ;db "[ window number (0-7) ] [ address ]",3 ;db "[ we 0 020 ] [ we 2 _eeadr ] ",4 ;db "allows you to see eeprom memory contents while you step through code",5 ;dd do_nothing ;db ":wf ",1, " ў set up a file register watch window",2 ;db "[ window number (0-7) ] [ address ]",3 ;db "[ wf 0 01e ] [ wf 7 _indf ]",4 ;db "allows you to see file register memory contents while you step through code",5 ;dd do_nothing db ":write ",1, " ў write all data to the pic chip memory ",2 db " ",3 db "eg [ write ]$$",4 db "writes the program / eeprom and configuration memmory to the PIC$Be carefull of this command when using OTP devices.$NOTE. THE WRITE FUNCTION FOR D16F84A IS A DO NOTHING CALL",5 dd writepic db ":T ",1, " ў Trace one instruction except for calls, which are executed in one go",2 db " ў Trace one instruction except for calls, which are executed in one go",3 db "eg [ T ]$$",4 db "Execute the current instruction and follow normal program flow$$Note: Only one instruction is executed each time except for subroutines which$are executed in one go. All forms of BreakPoints apply$hotkey: F2$$",5 dd do_msf2 db 1 ;the end !!!!!!!!!!!! ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Store pmode stuff / load file / read pic ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл even 4 ; assume dword alignment in cr0 entry: ; it all starts here in 32 bit pmode cld mov d[optv86],eax mov d[optcs],ebx mov ax,cs mov w[sel_code],ax mov ax,ds mov w[sel_data],ax mov ax,es mov w[sel_flat],ax mov ax,fs mov w[sel_a000],ax mov ax,gs mov w[sel_b800],ax push ds pop es ; lods and stos work the same now mov eax,0305 xor ebx,ebx int 016 ; sort out keyboard typmatic rate mov ax,01112 int 010 ; 80 x 48 text mode with cls pop w[prntrprt] pop w[tmr] ; set up by p32 mov ecx,10000000 mov edi,010000 ; start of data area mov al,0 rep stosb ; clear all ram before loading hex file/and shrinkin hex call powerdown cmp b[080],0 jz long readpic ; if no command pars then read hex from pic call getpic ; read config and osccal from pic (NO EPROM) call getfile ; get the file info call loadfile ; load the ascii file call shrinkit ; turn the ascii into realtime code starting @ pic_mem call loadcodfile ; load in symbols from cod file jb @entry1 call get_fishy ; jnc @entry1 ;mov b[codfile],0 ; cod was loaded but is corrupted mark as not loaded @entry1: call pic_por ; set up the registers for a power up reset condition call powerup ;********************** call vppoff jmp do_cls breakkey: ; key press causing break mov ebx,btxt1 call do_breakcmd jmp start breakpoint: ; standard w[_brk] holds the same as [_ip] mov ebx,btxt2 call do_breakcmd jmp start breakeyeb: ; byte in eye mov ebx,btxt3 call do_breakcmd jmp start breakeyew: ; word in eye mov ebx,btxt4 call do_breakcmd jmp start breakeyed: ; dword in eye mov ebx,btxt5 call do_breakcmd jmp start breakwdt: ; watch dog time out mov ebx,btxt6 call do_breakcmd jmp start breakwupc: ; wakeup on pin change from sleep mov ebx,btxt7 call do_breakcmd jmp start breakmclr: ; master clear reset pin activated mov ebx,btxt8 call do_breakcmd jmp start breakexec: ; key press causing break mov ebx,btxt9 call do_breakcmd jmp start start: call docursor ; move the cursor and/or scroll the box call do_screen ; do the lot, prep / vscreen / vga call getstring ; display entry box and help line at bottom call put_kbuf0 ; output the kbuf text to screen, scroll it etc mov al,b[kbuf0] ; now then getstring has something lets see what it is cmp al,0 ; is there anything typed ? jz start ; if not then do no more and repeat main loop mov esi,command ; pointer to command heap mov edi,kbuf0+1 ; pointer to keyboard buffer movzx ecx,b[kbuf0] ; ecx=number of characters typed, 0 was checked earlier start1: xor eax,eax ; ready for error 0 lodsb ; get first character (should be a colon) cmp al,0 ; 0 means end of heap, eax already zero and al = 0 means eax = 0 = bad command jz long do_badcmd ; if a sucessfull command was found we would not be here ! cmp al,1 ; 1 means skip into extended help found in unique device .32 jnz start1a mov esi,command1 ; repoint to extended help lodsb ; get the first char and carry on start1a: call start_cmp ; compare the strings upto the space etc jc start3 ; not compatible so find next colon start2: ; if here it was a match so find the execute address and exit lodsb ; looking for 5 cmp al,5 jnz start2 lodsd ; eax = address of code and esi = start of colon or 0 again mov d[godoit],eax ; setup the execute address xchg esi,edi ; esi now points to keyboard movzx ecx,b[kbuf0] ; set up buffer length call redline ; do a red line for execute jmp d[godoit] ; the destination routine should end by jmping to start start3: ; if here it was a match so find the execute address and exit lodsb ; looking for 5, the next dword is the execute address cmp al,5 jnz start3 ; filter out the crap lodsd ; eax = address of code and esi = start of colon or 0 again jmp start1 ; repeat until end of heap is found ! start_cmp: ; on entry esi , edi point to strings ecx = number of bytes push eax,esi,edi,ecx start_cmp0: mov al,b[esi] ; command heap cmp al,1 jz start_cmp_yes ; if here then "wxyz ",1 has been found !!!! a match yes cmp al,b[edi] ; kbuf0 jnz start_cmp_no inc edi inc esi loop start_cmp0 lodsb ; get next character from dest string (it may not have a space in it( cmp al,020 ; if a space then we have a unique positive match so go onto stage 1 jnz start_cmp_no ; if no space, then a match was found for the first ??? characters, but there are more so not a complete match ! jmp start_cmp_yes ; if so then treat as special else no other comands are listed start_cmp_yes: pop ecx,edi,esi,eax clc ; ok a match found ret ; if unique then stage is set up start_cmp_no: pop ecx,edi,esi,eax stc ; error ret ;on entry esi = address of string typed ; edi = address of compare string, must end in 1 ; ecx = no of characters to cmp ;carry set if no match ;carry clear if ok ;routine exits out when al=1 compare: ; on entry esi , edi point to strings ecx = number of bytes push eax,esi,edi,ecx compare0: mov al,b[edi] ; var heap cmp al,1 jz compare_no ; if here then "wxyz",1 has been found !!!! but we still have more to go, so must be wrong string cmp al,2 jz compare_no ; if here then "wxyz",2 has been found !!!! but we still have more to go, so must be wrong string cmp al,4 jz compare_no ; if here then "wxyz",4 has been found !!!! but we still have more to go, so must be wrong string cmp al,b[esi] ; if not then lets compare the two bytes jnz compare_no ; not the same ? inc edi ; move on inc esi loop compare0 cmp b[edi],4 ; a complete compare ? ja compare_no ; if not then everything type compared ok but dest string still has more compare_yes: pop ecx,edi,esi,eax clc ; ok a match found ret ; if unique then stage is set up compare_no: pop ecx,edi,esi,eax stc ; error ret put_kbuf0: ; output the kbuf text to screen, scroll it etc mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov esi,kbuf0 ; the string to copy lodsb ; how many chars to copy movzx ecx,al ; get ready for loop mov d[kbufz],ecx rep movsb ; do it, now update cursor to next line (could be an error or output response such as help etc) inc b[cursor] ; something typed with ret pressed so inc pointer ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Do_?????? Routines ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;on entry ; esi = start of kbuf0 string (1st character, not the string length) ; ecx = length of the string ; edi = 0 or a colon for the next command in the heap ;---------------------- ; DONE ! do_about: mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits dec edi ; we have to do this because call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,-1 mov esi,pidt ; program ID text or help command text xor bx,bx ; x,y of cursor do_about0: lodsb ; get first char of pidt text or al,al ; end of the pidt text ? jz do_about1 ; if so then carry on with header text stosb ; else store inc bl ; move x,y cursor loop do_about0 ; infinite loop do_about1: mov esi,abouttext do_about2: lodsb cmp al,"$" ; new line ? jz do_about_nl cmp al,0 ; end of string jz long start cmp al,4 ; end of string jz long start cmp al,5 ; end of help text ? jz long do_helpcmd2 ; if a five then go back to docmd routine to do the examples stosb inc bl ; inc x loop do_about2 jmp long start ; should not get here do_about_nl: inc b[cursor] mov eax,80 sub al,bl add edi,eax inc bh xor bl,bl cmp bh,b[do_help-1] ; lines until key needed jae do_about_nl1 pushad call docursor call do_screen popad jmp do_about2 do_about_nl1: call newline ; update screen, wait for keypress etc jmp do_about2 ;---------------------- ; DONE ! do_fast: ; or b[turbo],1 call do_goodcmd jmp start ; bit 0 set (fst mode on) ;---------------------- ; DONE ! do_slow: ; and b[turbo],0fe call do_goodcmd jmp start ; bit 0 cleared (slow mode now) ;---------------------- ; DONE ! do_style: ; xor b[mcx86],1 ; toggle bit 1 call do_goodcmd jmp start ; BPX stored ! now go back to start ;---------------------- ; DONE ! do_bpx: ; call get_cli_hex4 ; on exit eax = value, carry set if error and eax holds error code jc long do_badcmd ; do error if there is one call set_bpx ; routine to set bpx in parallel code jc long do_badcmd ; error, eax already set up. call do_goodcmd jmp start ; BPX stored ! now go back to start ;---------------------- ; DONE ! do_bpl: ; call do_goodcmd mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,d[wrapmem] mov ebp,0 mov esi,0 mov bx,0100 dec esi ;---------------------- ; DONE ! do_bpl1: inc esi ; IP address 0000 to 03fff mov al,b[esi*4+BPXMEM] ; get the shit. low word = bpx info, high word = original opcode and al,1 ; if not zero then must be a duplicate breakpoint, so do error jnz do_bplyes ; found a breakpoint do_bpl2: ; if not then keep going until exhausted ! loop do_bpl1 inc b[cursor] inc b[cursor] jmp start ; all done, this is the only way out of here do_bplyes: ; if here we have a break point mov eax,esi ; put address into eax call convert_16k ; yeah stosd ; store ascii into CLIBUFF inc edi ; a space between values is nice add bl,5 inc ebp ; room for 16 of em before new line is needed cmp ebp,16 ; 16 done yet ? jnz do_bpl1 ; if not keep going call do_bpl_nl jmp do_bpl1 do_bpl_nl: ; do bpl new line inc b[cursor] mov eax,80 sub al,bl add edi,eax inc bh xor ebp,ebp xor bl,bl cmp bh,b[do_help-1] ; lines until key needed jae do_bpl_nl1 pushad call docursor call do_screen popad ret do_bpl_nl1: call newline ; update screen, wait for keypress etc ret ;---------------------- ; do_bpe: ; ;setup bpx address ;and set flags for pcl,fosc,or file register ;which should trap at simpic0 inc b[van8-1] and b[van8-1],07 dec w[van3+4] jmp start ;---------------------- ; DONE ! do_reset: push start ; this is where we want por to return call do_goodcmd jmp pic_por ; no return from here ;---------------------- ; DONE ! do_rdx: xor b[turbo],020 jmp start ; no return from here ;---------------------- ; DONE ! do_cls: mov ecx,65535*80 ; total CLIBUFF memory 5 megs mov al,020 ; space mov edi,CLIBUFF rep stosb mov w[cli_top+4],0 ;reset the offset pointer mov d[cli_top],0 mov b[cursor],0 ;reset the cursor jmp start ;---------------------- ; DONE ! do_trace: call get_cli_hex8 ; on exit eax = value, carry set if error and eax holds error code jnc do_trace1 ; if no error then carry on cmp eax,1 ; if no parameters found then we want to do a simple msf5 jnz long do_badcmd ; if any other error then do bad command else do infinite loop jmp do_ssf1 do_trace1: push eax call get_time ; get the time and reset the ebp counter pop edi ; edi = number of ebp to do do_trace2: call fastdecode cmp ebp,edi ; breakout ? jz long breakexec call simpic test b[turbo],1 jnz do_trace2 ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_trace2 ;---------------------- ; DONE ! do_go: ; called by get_cli KBUF holds valid command lets see if it contains data pushad call get_cli_xpr ; carry set if expression is present jnc do_go2 ; go do it popad call get_cli_hex4 ; on exit eax = value, carry set if error and eax holds error code jnc do_go1 ; if no error then carry on cmp eax,1 ; if no parameters found then we want to set a silly address and go for ever jnz long do_badcmd ; if any other error then do bad command else do infinite loop mov ax,0ffff ; this address will never get reached !! do_go1: mov w[_brk],ax ; break now holds the next address (the one that is skipped to) call do_goodcmd call get_time call fastdecode ; this is a ssf1 call call simpic ; which will trace over the current bpx if we are at one ! jmp do_msf5a ; go and do multi steps until brk is found do_go2: mov d[do_mseye_b+1],esi ; insert operand into code mov d[do_mseye_w+2],esi ; insert operand into code mov d[do_mseye_d+1],esi ; insert operand into code popad jmp do_mseye ; go do conditional go, ie go fosc=20 ;---------------------- db 0 ; number of lines in command window. used to tell when to stop scrolling long text do_help: call get_cli_cmd ; on exit edi = address of complete string found from the command tail kbuf0 input else error jnc long do_helpcmd ; if no error then carry on and do help on specific command cmp eax,1 ; if no parameters found then we want general help jnz long do_badcmd ; if any other error then do bad command else do infinite loop call do_goodcmd ; on entry eax holds error number mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,-1 ; infinite loop, lloking for zero to exit this routine back to start mov esi,command ; the start of the command text area mov bx,0100 ; x,y of cursor starts at zero,zero do_help1: mov ebp,08000 ; Expected data not found. (fatal error codes) xor eax,eax lodsb ; looking for a colon (start of a block) cmp al,1 ; 1 means skip into extended help found in unique device .32 jnz do_help1a mov esi,command1 ; repoint to extended help lodsb ; get the first char and carry on do_help1a: cmp al,0 ; this is the end of extended help ! jz long start ; quit out. THIS IS THE ONLY WAY OUT FROM HERE cmp al,":" ; if here this must be a colon else error jnz long fatal_error ; expected data not found serious error it should either be a zero or a colon nothing else do_help2: ; stage 1 * xfer command mov dl,1 ; transfer text until terminate byte = 1 mov ebp,edi ; save start of line pointer call do_helpxfer ; transfer upto dl byte mov eax,020202020 stosd stosd ; delete any stray text from cursor mov edi,ebp ; restore beginning of line add edi,8 ; mov on 8 places mov bl,8 ; set cursor to same mov dl,2 ; transfer text until terminate byte = 2 call do_helpxfer ; transfer upto dl byte call do_help_nl ; new line do_help3: ; stage 2 * find start of next command lodsb ; get data cmp al,5 ; end of the command text ? jnz do_help3 ; if not keep going until it is found add esi,4 jmp do_help1 do_helpxfer: lodsb ; if here then this is the first character of the command after the colon cmp al,dl ; string terminate byte ? jz ret ; if so then exit, esi is pointing past terminate byte to next valid ascii text stosb ; else store character and carry on until a 1 is found inc bl ; inc x cursor loop do_helpxfer ; looking for a string terminate byte in dl to exit this stage of the routine mov ebp,08001 ; error code jmp fatal_error ; infinite loop timed out do_help_nl: inc b[cursor] ; do new line mov eax,80 ; characters per line sub al,bl ; how many spaces left until start of next line add edi,eax ; edi now pointing to the start of a new line inc bh ; inc y position (we need pause button here) xor bl,bl ; new line creates a fresh zero x pos cmp bh,b[do_help-1] ; lines until key needed jae do_help_nl1 pushad call docursor call do_screen popad ret do_help_nl1: call newline ; update screen, wait for keypress etc ret ;---------------------- ; DONE ! dd 0 do_helpcmd: call do_goodcmd ; on entry eax holds error number xchg esi,edi do_helpcmd0: lodsb cmp al,3 ; looking for start of example jnz do_helpcmd0 mov d[do_helpcmd-4],esi do_helpcmd1: lodsb cmp al,4 ; looking for start of extended help jnz do_helpcmd1 mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits push esi ; save this call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,-1 ; infinite loop, lloking for zero to exit this routine back to start pop esi ; the start of the command text upto the 5 for end mov bx,0100 ; x,y of cursor starts at zero,zero is where the ok bit goes so text must go at 0,1 down jmp do_about2 ; this will exit back to here if ok do_helpcmd2: mov esi,d[do_helpcmd-4] jmp do_about2 ; no return from here ;--------------------- ; DONE ! do_hotkeys: mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits dec edi ; we have to do this because call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,-1 xor bx,bx ; x,y of cursor mov esi,hotkeytext jmp do_about2 ; carry on with output ;--------------------- ; DONE ! do_jmp: ; called by get_cli call get_cli_hex4 ; on exit eax = value, carry set if error and eax holds error code jc long do_badcmd ; do error if there is one call set_ip ; routine to ip to specified value jc long do_badcmd ; error, eax already set up. call do_goodcmd jmp start ; BPX stored ! now go back to start ;---------------------- ; DONE ! do_vars: ; called by get_cli KBUF holds valid command lets see if it contains data call do_goodcmd ; on entry eax holds error number pushad call get_cli_xpr ; carry set if expression is present jnc do_vars1 ; go do it popad mov ax,7 jmp do_badcmd ; if any other error then do bad command else do infinite loop do_vars1: ; if here eyedata holds 0 if a varl variable was used as the destination cmp d[eyedata],0 ; jnz do_vars2 ; if not zero then it was a fixed value so we simply addxlat into indf setting up esi to correct address ; otherwise if it was zero then esi is already holding the correct address set up as it was a varl variable and eax,d[wrapindf] ; each device is different add eax,_indf ; eax pints to file register mov esi,eax ; we need a bounds check, 12c508 has less mem that 16f877 do_vars2: mov eax,d[eyedata+4] ; get data and mov cl,b[eyedata+8] ; byte width cmp cl,1 ;byte ? jz do_vars1_b cmp cl,2 ;word ? jz do_vars1_w cmp cl,4 ;dword ? jz do_vars1_d popad mov eax,7 jmp do_badcmd do_vars1_b: mov b[esi],al ; insert operand into code jmp do_vars1_exit do_vars1_w: mov w[esi],ax ; insert operand into code jmp do_vars1_exit do_vars1_d: mov d[esi],eax ; insert operand into code jmp do_vars1_exit do_vars1_exit: popad jmp start ; back to the start ;---------------------- ; DONE ! do_varl: call do_goodcmd ; on entry eax holds error number inc b[cursor] mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,-1 ; infinite loop, lloking for zero to exit this routine back to start mov esi,variable ; the start of the variable heap mov bx,0100 ; x,y of cursor starts at zero,zero do_varl1: mov ebp,08000 ; Expected data not found. (fatal error codes) xor eax,eax lodsb ; looking for a colon (start of a block) dec esi cmp al,0 ; this is the end of varl ! jz long start ; quit out. THIS IS THE ONLY WAY OUT FROM HERE do_varl2: ; stage 1 * xfer command mov dl,4 ; transfer text until terminate byte <=4 call do_varlxfer ; transfer upto dl byte, esi = start of 32 bit address call do_varl_nl ; new line add esi,4 ; skip vector address jmp do_varl1 ; repeat until 0 comes up do_varlxfer: lodsb ; if here then this is the first character of the command after the colon cmp al,dl ; string terminate byte ? jbe ret ; if so then exit, esi is pointing past terminate byte to next valid ascii text stosb ; else store character and carry on until a 1 is found inc bl ; inc x cursor loop do_varlxfer ; looking for a string terminate byte in dl to exit this stage of the routine mov ebp,08001 ; error code jmp fatal_error ; infinite loop timed out do_varl_nl: inc b[cursor] ; do new line mov eax,80 ; characters per line sub al,bl ; how many spaces left until start of next line add edi,eax ; edi now pointing to the start of a new line inc bh ; inc y position (we need pause button here) xor bl,bl ; new line creates a fresh zero x pos cmp bh,b[do_help-1] ; lines until key needed ja do_varl_nl1 pushad call docursor call do_screen popad ret do_varl_nl1: call newline ; update screen, wait for keypress etc ret ;---------------------- ; DONE ! do_varh: jmp start ;---------------------- ; DONE ! do_peek: call do_goodcmd ; on entry eax holds error number inc b[cursor] mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,-1 ; infinite loop, lloking for zero to exit this routine back to start mov esi,int_var_heap ; the start of the variable heap mov bx,0100 ; x,y of cursor starts at zero,zero do_peek1: mov ebp,08000 ; Expected data not found. (fatal error codes) xor eax,eax lodsb ; get first chatacter dec esi cmp al,0 ; this is the end of peek ! jz long start ; quit out. THIS IS THE ONLY WAY OUT FROM HERE do_peek2: ; stage 1 * xfer command mov dl,4 ; transfer text until terminate byte <=4 call do_peekxfer ; transfer upto dl byte, esi = start of 32 bit address mov dl,al ; dl now holds 1,2,4 for byte word dword mov ax,02020 stosw lodsd ; get 32 bit address of where 1,2,4 is stored push eax call cnvrt_rdx_32hex ; output 32 bit value, using radix bit to do dec or hex pop eax add bl,10 push esi mov esi,eax xor eax,eax cmp dl,4 jnz @do_peek2a lodsd ; if 4 then get dword jmp do_peek3 @do_peek2a: cmp dl,2 jnz @do_peek2b lodsw jmp do_peek3 @do_peek2b: lodsb do_peek3: pop esi call cnvrt_rdx_32hex ; output 32 bit value, using radix bit to do dec or hex add bl,12 call do_peek_nl ; new line jmp do_peek1 ; repeat until 0 comes up do_peekxfer: lodsb ; if here then this is the first character of the command after the colon cmp al,dl ; string terminate byte ? jbe ret ; if so then exit, esi is pointing past terminate byte to next valid ascii text stosb ; else store character and carry on until a 1 is found inc bl ; inc x cursor loop do_peekxfer ; looking for a string terminate byte in dl to exit this stage of the routine mov ebp,08001 ; error code jmp fatal_error ; infinite loop timed out do_peek_nl: inc b[cursor] ; do new line mov eax,80 ; characters per line sub al,bl ; how many spaces left until start of next line add edi,eax ; edi now pointing to the start of a new line inc bh ; inc y position (we need pause button here) xor bl,bl ; new line creates a fresh zero x pos cmp bh,b[do_help-1] ; lines until key needed ja do_peek_nl1 pushad call docursor call do_screen popad ret do_peek_nl1: call newline ; update screen, wait for keypress etc ret ;---------------------- ; DONE ! do_nothing: ; null call for commands with no routines written yet jmp start ; remember to update command heap execute addresses ;---------------------- ; DONE ! do_togwin: ; used by F10 xchg al,b[twf] ; toggles the file register window and al,1 ; mask bit 0 xor al,1 ; invert bit xchg al,b[twf] ; twf = toggle win flag jmp start ; all done ;---------------------- ; DONE ! do_codewin: ; toggles window 2 from file to oppcode display call get_cli_hex2 ; on exit eax = value, carry set if error and eax holds error code jnc do_codewin2 ; bad text or no text in cli must be a hex or dec value cmp eax,1 ; if no parameters found then must be a toggle jnz long do_badcmd ; if any other error then do bad command else toggle do_codewin1: ; if 0 or nothing typed mov b[twf],1 ; twf = toggle win flag, 0 = file or 1 = code call do_goodcmd call shpageup_ret call shpagedn_ret jmp start ; all done do_codewin2: ; if here eax holds the number of lines to adjust movzx ebx,w[van3+2] ; get max on screen value cmp eax,ebx ; is it higher ? jbe do_codewin3 ; if below it's ok... mov eax,3 ; value out of range jmp do_badcmd ; yup do error in text window do_codewin3: ; if here then it is within range or ew has been adjusted so try again mov bp,ax ; copy lines asked for or ax,ax ; if zero then just toggle jz do_codewin1 ; and treat zero as if no parameters were included dec ax ; 0 = 1 line so 010 = 17 lines so dec to make 010 = 16 lines mov bx,ax ; copy to bx lines asked for mov cx,45 ; total lines available call getused_l ; on exit ax = lines used sub ax,w[van3+4] ; remove the current code win lines from the equation sub cx,ax ; if goes below then serious error !!!!!!!! cmp bx,cx ; compare lines asked for with lines available. jb do_codewin4 ; if below then plenty of lines available for lines asked for mov bx,w[van2+4] ; get the current eprom window lines or bx,bx ; is the eprom window switched off ie least lines jz do_codewin3a ; if so then no more adjusting of eprom, must adjust lines asked for shr w[van2+4],1 ; else half the number of lines in the eprom windiw mov ax,bp ; restore the original lines asked for jmp do_codewin3 ; and do it all again do_codewin3a: mov bx,cx ; if not then set lines asked for to lines available do_codewin4: mov w[van3+4],bx ; its ok to store as limits have been checked !! jmp do_codewin1 ;---------------------- ; DONE ! do_eprmwin: ; toggles eprom window call get_cli_hex2 ; on exit eax = value, carry set if error and eax holds error code jnc do_eprmwin2 ; bad text or no text in cli must be a hex or dec value cmp eax,1 ; if no parameters found then must be a toggle jnz long do_badcmd ; if any other error then do bad command else toggle do_eprmwin1: ; if 0 or nothing typed xor eax,eax mov bx,w[van2+4] ; get current value or bx,bx ; is it zero jnz do_eprmwin2 ; if not zero then set to zero, eax already = 0 so toggle it off movzx eax,w[van2+2] ; get max on screen value and toggle it on inc b[greenln] ; if here then we are switching the window on, so adjust the nol due to extra green line !!!!!!!!!!!!!!!!!! do_eprmwin2: ; if here eax holds the number of lines to adjust movzx ebx,w[van2+2] ; get max on screen value cmp eax,ebx ; is it higher ? jbe do_eprmwin3 ; if below it's ok... mov eax,3 ; value out of range jmp do_badcmd ; yup do error in text window do_eprmwin3: ; if here then it is within range mov bp,ax ; copy lines asked for mov bx,ax ; copy to bx lines asked for mov cx,45 ; total lines available call getused_l ; on exit ax = lines used sub ax,w[van2+4] ; remove the current code win lines from the equation sub cx,ax ; if goes below then serious error !!!!!!!! cmp bx,cx ; compare lines asked for with lines available. jb do_eprmwin4 ; if below then plenty of lines available for lines asked for mov bx,w[van3+4] ; get the current code/file window lines or bx,bx ; is the code window at is minimum ie least lines jz do_eprmwin3a ; if so then no more adjusting of eprom, must adjust lines asked for shr w[van3+4],1 ; else half the number of lines in the code window mov ax,bp ; restore the original lines asked for jmp do_eprmwin3 ; and do it all again do_eprmwin3a: mov bx,cx ; if not then set lines asked for to lines available do_eprmwin4: mov w[van2+4],bx ; its ok to store as limits have been checked !! call do_goodcmd jmp long start ;----------------- do_filewin: ; toggles window 2 from file to oppcode display call get_cli_hex2 ; on exit eax = value, carry set if error and eax holds error code jnc do_filewin2 ; bad text or no text in cli must be a hex or dec value cmp eax,1 ; if no parameters found then must be a toggle jnz long do_badcmd ; if any other error then do bad command else toggle do_filewin1: ; if 0 or nothing typed mov b[twf],0 ; twf = toggle win flag, 0 = file or 1 = code call do_goodcmd call shpageup_ret call shpagedn_ret jmp start ; all done do_filewin2: ; if here eax holds the number of lines to adjust movzx ebx,w[van3+2] ; get max on screen value cmp eax,ebx ; is it higher ? jbe do_filewin3 ; if below it's ok... mov eax,3 ; value out of range jmp do_badcmd ; yup do error in text window do_filewin3: ; if here then it is within range mov bp,ax or ax,ax ; if zero then just toggle jz do_filewin1 ; and treat zero as if no parameters were included dec ax ; 0 = 1 line so 010 = 17 lines so dec to make 010 = 16 lines mov bx,ax ; copy to bx lines asked for mov cx,45 ; total lines available call getused_l ; on exit ax = lines used sub ax,w[van3+4] ; remove the current code win lines from the equation sub cx,ax ; if goes below then serious error !!!!!!!! cmp bx,cx ; compare lines asked for with lines available. jb do_filewin4 ; if below then plenty of lines available for lines asked for mov bx,cx ; if not then set lines asked for to lines available mov bx,w[van2+4] ; get the current eprom window lines or bx,bx ; is the eprom window switched off ie least lines jz do_filewin3a ; if so then no more adjusting of eprom, must adjust lines asked for shr w[van2+4],1 ; else half the number of lines in the eprom windiw mov ax,bp ; restore the original lines asked for jmp do_filewin3 ; and do it all again do_filewin3a: mov bx,cx ; if not then set lines asked for to lines available do_filewin4: mov w[van3+4],bx ; its ok to store as limits have been checked !! jmp do_filewin1 asciiz2: db "PICDEBUG.LST",0 f2handle: dd 0 ;----------------- do_dump: and b[turbo],0bf ; set to NO COLOUR attributes in dump mov edx,asciiz2 xor ecx,ecx ; normal file mov eax,03c00 int 021 ; create file mov d[f2handle],eax ; save handle mov bp,0 ; yes we want to display the decoded string. push w[_ip] ; we must save this onto stack mov cx,0ffff ; get the highest memory location mov w[_ip],cx ; put into ip (we will restore this at the end) push w[_altip] ; this is altered by wrap_ip call wrap_ip ; on exit _IP holds the highest value possible pop w[_altip] ; put it back xor ecx,ecx ; start position xchg cx,w[_ip] ; cx = loop value and _ip = start position inc ecx ; now goes from 0000 to 0fff etc do_dump3: ; now loop from NOL to zero push ecx ; save counter call decodepic ; xfer mnemonic string and set up variables for simpic mov ax,0a0d stosw mov edx,080 ; start address of decode string sub edi,edx ; get rid of displacement (whats left is how long the string is) mov ecx,edi ; this is how many chars to copy for the line mov ax,04000 ; write file mov bx,w[f2handle] ; handle int 021 ; write ecx bytes from ds:edx address ;jc sdfsdfsdfsdf ; error ? inc w[_ip] ; next ip pop ecx ; loop loop do_dump3 ; keep going until all done mov ax,03e00 ; close file mov bx,w[f2handle] int 021 ; close data file pop w[_ip] ; restore this or b[turbo],040 ; set to yes we want COLOUR attributes in dump jmp start ;----------------- docursor: ; whenever getstring is exitied the cursor is moved down one line from its current pos mov bx,48 ; 48 means 0 to 48 = 49 lines of VGA, the next line is the blue line call getused_l ; on exit ax = lines left sub bx,ax ; bx = lines left on screen movzx ax,b[cursor] ; get y pos of cursor cmp ax,bx ; compare with number of lines available jbe ret ; if below or equal then quit else if above then scroll text sub ax,bx ; ax = how many lines the cursor is over mov b[cursor],bl ; set cursor to max y pos add w[cli_top+4],ax ; move text window base pointer movzx edi,w[cli_top+4] ; get newley updated pointer call mull_160 shr edi,1 ; now times 80 mov d[cli_top],edi ; set new address pushad mov ax,0200 ;set cursor mov bx,0 ;page number mov dh,b[cursor] ;line number (0 to 10) 01303 ;03,19 pos for cursor add dh,b[van4] ;makes a max of 50 mov dl,b[kbuf0] ;x pos of cursor inc dl int 010 popad ret newline: ; update screen, wait for keypress etc pushad call docursor call do_screen mov ecx,80 mov esi,bluetext+240 mov edi,49*160 mov es,w[sel_b800] newline1: movsb inc edi loop newline1 mov es,w[sel_data] call getkey popad mov bh,1 ; put bh back to 1 again ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Error reporting etc ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;0 = no such command ;1 = no parameters found ;2 = bad hex value (use digits 0 - F only) ;3 = value out of range or just plain silly ;4 = Bad decimal value (use digits 0 - 9 only) ;5 = string or parameter not found ;6 = No such variable exists ?, check spelling ;7 = Bad expression errortxt: db "ERROR: " goodtxt: db " Ok. " breaktxt: db " *** Break due to " breaktxt0: db " " btxt1: db "Key Press " btxt2: db "IP = BreakPoint " btxt3: db "Register Monitor " btxt4: db "Register Monitor " btxt5: db "Register Monitor " btxt6: db "Woof Woof TimeOut " btxt7: db "WakeUp on PinChange " btxt8: db "Master Clear Reset " btxt9: db "command completed " do_badcmd: ; on entry eax holds error number mov ebp,eax ; copy the error code mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area mov ecx,7 mov esi,errortxt rep movsb mov eax,ebp call convert_16k stosd add b[cursor],2 mov d[kbuf0+80],0 jmp start do_goodcmd: ; on entry eax holds error number pushad mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits dec edi ; we have to do this because call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area add edi,d[kbufz] mov ecx,7 mov esi,goodtxt rep movsb popad ret do_breakcmd: ; on entry ebx holds txt and ebp = counter for number of instructions executed pushad mov ah,0 int 01a sub edx,d[tmr_ticks] mov eax,edx mov edi,breaktxt0 ; output string for clock counts etc. call cnvrt_rdx_32 ; output 32 bit value, using radix bit to do dec or hex mov eax,ebp add edi,4 call cnvrt_rdx_32 ; output 32 bit value, using radix bit to do dec or hex mov ax,w[cli_top+4] ; line pointer (0 to 65535) movzx edi,b[cursor] ; cursor pos add di,ax ; auto and 0ffff by using the low 16 bits call mull_160 shr edi,1 ; * 80 characters per line add edi,CLIBUFF ; point to the text area add edi,d[kbufz] mov ecx,20 mov esi,breaktxt rep movsb mov ecx,20 mov esi,ebx ; ebx came in on entry to this routine rep movsb mov esi,breaktxt0 ; seconds/number of doodahs etc mov ecx,30 rep movsb popad ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;AUX routines for all do_something code ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;on entry eax = 16 bit value of address specified set_bpx: mov esi,eax ; else get the specified BPX address mov eax,3 ; bad address cmp esi,d[wrapmem] ja set_bpx_bad ; silly memory address inc eax ; duplicate break point error code (4) xor b[esi*4+BPXMEM],1 ; toggle bpx clc ret set_bpx_bad: stc ; error already set up ret ;----------------- set_ip: mov esi,eax ; else get the specified BPX address mov eax,3 ; bad address cmp esi,d[wrapmem] ja set_bpx_bad ; silly memory address mov w[_IP],si ; set IP clc ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;The main command tail evaluation routines ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;on entry stack holds 1 ret address from start ; esi = start of kbuf0 string (1st character, not the string length) ; ecx = length of the string ; edi = 0 or a colon for the next command in the heap ; ;on exit eax = 16 bit value high eax is cleared, carry = clear if ok ; eax = error code, carry = set if error ;@loop1_? get_cli_hex2: ; if no data then just exit with no temp bpx get_cli_hex4: ; if no data then just exit with no temp bpx get_cli_hex8: ; if no data then just exit with no temp bpx mov b[eyedata+8],0 ; marker! if this is a variable then var routine will set this to either 1,2 or 4 lodsb cmp al,020 ; looking for the space between command and the data data which has a space just before it jz @loop1_1 loop get_cli_hex8 ; continue until either a space is found or we exhaust the string mov eax,1 ; no parameters found stc ret ; error @loop1_1: ; if here we need to find the first char of the parameter lodsb cmp al,020 ; another space ? jnz @loop1_2 ; if not it must be the first character of the parameter loop @loop1_1 mov eax,1 ; no parameters found stc ret ; error @loop1_2: ; if here then we have found the first character of the pars cmp al,"+" ; a relative jmp ? ;jz plusdir cmp al,"-" ; a relative jump ? ;jz negdir call get_cli_value ; evaluate the string, hex or dec or equation and return in eax ret ; eax already holds the error code if there is one and the carry will be set ; else carry is clear and eax holds the data ;----------------------- ;on entry... see above for all get_ routines ;on entry stack holds 1 ret address from start ; esi = start of kbuf0 string (1st character, not the string length) ; ecx = length of the string ; edi = 0 no more data or a colon for the next command in the heap ; ;on exit edi = address of command heap where text can be found for help ; eax = error code, carry = set if error ;@loop2_? get_cli_cmd: ; if no data then just exit with no temp bpx lodsb cmp al,020 ; looking for the space between command and the data data which has a space just before it jz @loop2_1 loop get_cli_cmd ; continue until either a space is found or we exhaust the string mov eax,1 ; no parameters found stc ret ; error @loop2_1: ; if here we need to find the first char of the parameter lodsb cmp al,020 ; another space ? jnz @loop2_2 ; if not it must be the first character of the parameter loop @loop2_1 mov eax,1 ; no parameters found, just a pile of spaces stc ret ; error @loop2_2: ; if here then we have found the first character of the pars dec ecx ; always 1 more than what is typed dec esi ; restore the losdb pointer to the first character of the parameter mov edi,command+1 ; edi = start of command just past the : xchg esi,edi ; swapem it's easier to use esi to scan command heap @loop2_3: ; search command heap for match call general_cmp ; compare ecx characters at esi and edi, carry set on error (no match) jnc @loop2_5 ; found one ? @loop2_4: ; if here there was no match so go on and find another possible one lodsb ; looking for a 5 cmp al,5 jnz @loop2_4 lodsd ; skip the 32 bit offset address lodsb ; if 0 then exit out with error, else do it all again cmp al,1 ; move into extended help ? jnz @loop2_6 mov esi,command1 lodsb @loop2_6: cmp al,0 jnz @loop2_3 xchg esi,edi ; swapem it's easier to use esi to scan command heap mov eax,5 ; error, no such command found in help stc ret ; eax already holds the error code if there is one and the carry will be set @loop2_5: ; if here a match was found xchg esi,edi ; swapem it's easier to use esi to scan command heap clc ret ;on entry stack holds 1 ret address from start ; esi = start of kbuf0 string (1st character, not the string length) ; or !!! ; esi = start of hex/dec/equation string ; ecx = length of the string ; edi = 0 or a colon for the next command in the heap ; ;on exit eax = 32 bit value carry = clear if ok ; eax = error code, carry = set if error get_cli_xpr: ; if no data then just exit with no temp bpx lodsb cmp al,020 ; looking for the space between command and the data data which has a space just before it jz @loop3_1 loop get_cli_xpr ; continue until either a space is found or we exhaust the string mov eax,1 ; no parameters found stc ret ; error @loop3_1: ; if here we need to find the first char of the parameter mov al,b[esi] cmp al,020 ; another space ? jnz @loop3_2 ; if not it must be the first character of the parameter inc esi loop @loop3_1 mov eax,1 ; no parameters found stc ret ; error @loop3_2: ; if here then we have found the first character of the 1st par mov ebp,ecx ; get current string length inc ebp ; adjust ebp now contains length of parameter push esi ; save this @loop3_3: mov al,b[esi] cmp al,"=" ; end of first par ? jz @loop3_4 ; if so quit out inc esi loop @loop3_3 ; else search for it pop eax ; restore stack mov eax,7 ; error code stc ret ; Bad expression @loop3_4: ; if here we are pointing to the '=' and ecx = length of second par + 1 sub ebp,ecx ; ebp = length of first par + 1 push ebp ; this is the length of the first par, esi on stack mov b[esi],0 ; zero terminate string (get rid of '=') inc esi ; now pointing to first character of second par dec ecx ; make up for the inc lodsb ; al=first char. ecx is adjusted later. call get_cli_value ; evaluate the end par, hex or dec or equation and return in eax jc get_cli_xprbad ; ooh bad, pop stack and ret mov d[eyedata+4],eax ; store the physical value of the second parameter mov b[eyedata+8],bl ; and it's byte width pop ecx ; get the string length of the stack for the first par pop esi ; get the pointer to it too lodsb call get_cli_value ; evaluate the begin par, hex or dec or equation or variable and return in eax,bl jc get_cli_xprbad1 ; ooh bad, DO NOT pop stack and ret clc ret get_cli_xprbad: pop ecx,esi get_cli_xprbad1: stc mov eax,7 ; bad expression ret ;---------------------------------------------------------------------------- ;on entry al = first character ; esi = next character ; ecx = number of characters left in the string command ;on exit eax = value ; ebp = number of digits found ; esi = vector address of variable if one was used else esi = 0 ; ebx = 1,2,3,4 for byte,word,dword etc ; carry set on error ... eax = error code get_cli_value: ; carry set on error else eax holds value cmp al,"0" ; is it definately a hex number ? jz get_cli_value_hex ; if so go do the hex convert cmp al,":" ; is it a decimal number ? 0-9 : a - z jb get_cli_value_dec ; if so go do decimal convert jmp get_cli_value_var ; if here it must be a variable get_cli_value_hex: ; this does the hex stuff dec esi ; point esi back to where al came from dec ecx ; adjust loop counter xor edx,edx mov ebp,edx ; ebp = digit counter.... max of four ! @loop4_3: lodsb ; get first character of data mov bl,al ; mov to al cmp bl,039 ; test ascii digit 9 jbe @loop4_4 ; a number or letter ? and bl,05f ; convert to upper case if a letter sub bl,7 ; convert to a real value @loop4_4: ; if here its a number now sub bl,030 ; remove ascii leaving a value of 0 to 15 jb get_cli_value_hexbad ; bad hex value cmp bl,010 ; more than sixteen jae get_cli_value_hexbad ; bad hex value shl edx,4 ; make room for 1st nibble or dl,bl ; transfer nibble inc ebp ; increment digit counter loop @loop4_3 ; only the last 8 digits are used cmp ebp,9 ; maximum of 8 digits ever !!! ja ret ; ret out if more than 4 digits, carry and code already set up mov eax,edx call get_cli_eax ; bl = byte width mov d[eyedata],0 ; do_vars checks this for either a real 32 bit address or a pointer to file registers clc ret ; this is a good exit get_cli_value_hexbad: ; mov eax,2 ; bad hex digit stc ; set carry ret ; ret out get_cli_value_outrange: ; mov eax,3 ; bad hex digit stc ; set carry ret ; ret out get_cli_value_dec: ; this does the dec stuff dec esi ; although al = first character it mucks up ecx so dec esi to put it right again dec ecx xor edx,edx ; temp storage for calc's mov ebp,edx ; ebp = digit counter.... max of four ! mov ebx,edx ; the final sum goes here ! @loop1_5: lodsb ; get first character of data or al,al jz winky cmp al,039 ; test ascii digit 9 ja get_cli_value_baddec ; bad dec value sub al,030 ; remove ascii leaving a value of 0 to 9 jb get_cli_value_baddec ; bad dec value as it went below zero. movzx eax,al ; eax = al mov edx,ebx ; make the copy sal ebx,1 ; * 2 sal edx,3 ; * 8 add ebx,edx ; ebx = ebx * 10 add ebx,eax ; ebx = ebx + eax inc ebp ; increment digit counter loop @loop1_5 ; only the last 8 digits are used winky: mov eax,3 ; value out of range stc ; set error just in case cmp ebp,11 ; maximum of 10 decimal digits ever !!! ja ret ; ret out if more than 10 digits, carry and code already set up mov eax,ebx ; transfer value and clear error call get_cli_eax ; put byte width into ebx mov d[eyedata],0 ; do_vars checks this for either a real 32 bit address or a pointer to file registers clc ret ; this is a good exit get_cli_value_baddec: ; mov eax,4 ; bad dec digit stc ; set carry ret ; ret out get_cli_eax: ; scan eax and update ebx to 1,2,3,4 fo b , w , dword push eax xor ebx,ebx inc bl shr eax,8 jz @get_cli_eax1 ; if zero then a byte inc bl shr eax,8 jz @get_cli_eax1 ; if here then a word inc bl shr eax,8 jz @get_cli_eax1 inc bl shr eax,8 @get_cli_eax1: pop eax ret get_cli_value_var: ; this does the var stuff mov edi,variable ; variable heap start point dec esi ; although al = first character it mucks up ecx so dec esi to put it right again dec ecx xor edx,edx ; temp storage for calc's mov ebp,edx ; ebp = digit counter.... max of four ! mov ebx,edx ; the final sum goes here ! @loop1_6: cmp b[edi],0 ; have we exhausted the search ? jz get_cli_value_badvar call compare ; compare the two strings jnc @loop1_8 ; a match ? @loop1_7: mov al,b[edi] ; looking for end of line inc edi ; pointing and ready for the first character of the next variable when we exit here cmp al,4 ja @loop1_7 ; if above keep going or al,al ; is it a zero ? it should not be one unless weve made a programming error. jz get_cli_value_badvar ; if so quit out cos weve exhaused the var heap add edi,4 ; skip 32 bit address, now pointing to first character jmp @loop1_6 @loop1_8: ; if here a match was found, find the vector mov al,b[edi] ; looking for end of line again inc edi ; pointing and ready for the first character of the next variable when we exit here cmp al,4 ja @loop1_8 ; if above keep going ;on exit eax = value ; ebp = number of digits found ; eyedata = vector address of variable if one was used, and byte size mov b[eyedata+8],al ; store the number of bytes the variable contains mov bl,al mov eax,d[edi] ; get the vector address mov d[eyedata],eax ; store the vector address mov esi,eax ; xfer vector xor eax,eax cmp bl,1 ; is it byte data ? jz @loop1_9 cmp bl,2 ; is it word data ? jz @loop1_10 mov eax,d[esi] ; get dword data eax clc ret ; this is a good exit @loop1_9: ; get byte data al mov al,b[esi] ; don't mess with esi, we need it later on clc ret @loop1_10: ; get word data ax mov ax,w[esi] clc ret get_cli_value_badvar: ; mov eax,6 ; no such variable exists, check spelling stc ; set carry ret ; ret out get_time: pushad mov ah,0 int 01a mov d[tmr_ticks],edx popad xor ebp,ebp ret ;---------------------------------------------------------------------------- ;on entry edi = start of XVAN4 (code window) ;on exit XVAN4 filled with the symbol if one exists ; edi adjusted get_symbols: ; fill with symbols or just offset by 12 push eax cmp b[codfile],1 jnz long get_symbols_ncf ; quit out if no codfile mov ax,w[_ip] ; get ip ;blah get_symbols_ntt: ; here if NOT THIS TIME pop eax add edi,12 ; so pad out with spaces ret get_symbols_ncf: ; here if NO COD FILE pop eax ; no padding needed ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;The keyboard interface ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл getstring: ; this is a new search string so reset pointers mov b[kbuf0],0 mov ecx,0 ; length of string mov esi,kbuf0+1 ; search string buffer getstring0: cmp cl,0 ; empty key buffer ? jnz getstring1 ; if not then do not put default text into blue line pushad ; mov ecx,20 ; 20*4 = 80 characters to delete mov edi,bluetext mov esi,edi add esi,80 rep movsd ; copy default text ... type command or h for help popad getstring1: mov b[kbuf0],cl mov b[stage],0 ; reset stage number for blue line call blueline ; scan kbuf and update the bottom line with possibles call blueline_paint ; draws blue line on screen @ line 50 call getkey ; get key, bl = ascii value call hotkey ; check for hot keys etc, pop and goto start if pressed ; else carry on as normal cmp bl,8 ; DEL jnz getstring2 cmp cx,0 ; any characters to delete jz getstring0 ; if not repeat loop dec cx ; dec string length dec esi ; dec pointer cmp cx,0 ; check again if any characters to delete jz getstring0 ; if not repeat loop so blue text can have default string jmp getstring1 ; repeat main loop if more to delete etc getstring2: cmp bl,0d ; RET jnz getstring3 mov b[kbuf0],cl ; store string length mov b[kbuf0+80],cl ; DUPLICATE mov b[esi],0 ; terminate with a zero mov b[esi+80],0 ; DUPLICATE ret ; exit from routine getstring3: cmp ax,0100 ; ESC jnz getstring3a mov b[kbuf0],0 ; set string length to 0 mov b[kbuf0+80],0 ; DUPLICATE pop eax jmp start ; exit from routine getstring3a: or cl,cl ; F3 only works when current string pointer is zero jnz getstring4 ; if not zero then do not check for f3 cmp ax,03d00 ; F3 jnz getstring4 ; if not then carry on mov ecx,79 mov esi,kbuf0+80 mov edi,kbuf0 rep movsb ret getstring4: cmp cx,78 ; room for more text? jz getstring1 ; if not repeat loop mov al,bl ; put ascii character in al, and check for valid ascii value sub al,32 ; if al<32 al not a valid ascii character jb getstring1 ; if so do not store and repeat loop mov al,bl ; restore al and al,080 ; mask bit 7 from ascii character cmp al,080 ; if bit 7 set then al>127 which is not a valid ascii character jz getstring1 inc cx ; increase string length mov b[esi],bl ; store ascii character in buffer mov b[esi+80],bl inc esi ; mov si to next vacant location jmp getstring1 ret ; dummy ret getkey: mov ax,0 int 016 ; wait for key mov bx,ax mov ax,0200 int 016 ; get shift status, dont wait and al,03 mov ah,bh ; al = scan code, ah = ascii code mov bp,1 ret hotkey: pop d[temp] pop d[temp+4] ; restore stack ready for exit because we are in getstring and hotkey ;cmp bx,01f13 ; CTRL-S pressed ;cmp bx,01205 ; CTRL-E pressed ;cmp ax,01c00 ; RET pressed ;cmp bx,01e01 ; CTRL-A ;cmp bx,01312 ; CTRL-R ;cmp bx,01414 ; CTRL-T ;cmp ax,04b00 ; CURLEFT ;cmp ax,04d00 ; CURRIGHT ;cmp bx,02100 ; ALT F ;cmp ax,0f00 ; TAB ;cmp bx,01000 ; ALT-Q ;cmp bx,01300 ; ALT-R ;cmp bx,01f00 ; ALT-S ;cmp bx,03000 ; ALT-B ;cmp bx,01700 ; ALT-I ;cmp bx,01600 ; ALT-U ;cmp bx,02e00 ; ALT-C ;cmp bx,02267 ; G ;cmp bx,011b ; ESC ;cmp bx,02d00 ; ALT-X ;cmp ax,04100 ; F7 cmp ax,03b00 ; F1 jz long do_ssf1 ; do single step following normal instruction flow cmp ax,03c00 ; F2 jz long do_msf2 ; do single step but execute call routines in one go ;;;;;;;;cmp ax,03d00 ; F3 CAN NOT BE USED AS IT IS CHECKED ELSE WHERE cmp ax,03e00 ; F4 jz long do_msf4 ; do single step but trap at ip+1 cmp ax,03f00 ; F5 jz long do_msf5 ; do single step but trap at ip+2 if a skip instruction cmp ax,04800 ; CURUP jz long curup cmp ax,04802 ; SHIFT CURUP jz long shcurup cmp ax,05000 ; CURDOWN jz long curdown cmp ax,05002 ; SHIFT CURDOWN jz long shcurdown cmp ax,04400 ; F10 jz long do_togwin cmp ax,04900 ; PGUP jz long pageup cmp ax,05100 ; PGDN jz long pagedn cmp ax,04902 ; SHIFT PGUP jz long shpageup cmp ax,05102 ; SHIFT PGDN jz long shpagedn push d[temp+4] ; restore stack ready for exit because we are in getstring and hotkey jmp d[temp] ; just jump... no need to push and then ret !!!!! ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;the BLUELINE SHIT ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл redline: push ecx,edi,ds mov ds,w[sel_b800] mov edi,49*160 inc edi mov ecx,80 redline1: mov b[edi],035 add edi,2 loop redline1 pop ds,edi,ecx ret ;stage 0 puts all possible commands on the line ;stage 1 puts the description on the line ;stage 2 puts the required comand parameters on the line ;stage 3 signals end of blue line routine but godoit holds a valid execute address blueline: cmp b[kbuf0],0 ; nothing in the bufer ? jz long ret cmp b[stage],3 ; stage 3 ? jz long ret pushad ; else we must be doing stage 0 or stage 1 mov ecx,20 ; 20*4 = 80 characters to delete mov edi,bluetext mov eax,0 rep stosd ; clear the line mov esi,command ; pointer to command heap mov edi,bluetext mov ebp,kbuf0+1 movzx ecx,b[kbuf0] ; ecx=number of characters typed blueline1: lodsb ; get first character (should be a colon) cmp al,0 ; 0 means end of heap jz blueline_exit call blueline_cmp ; esi = ebp (ecx characters) carry set if no carry clear if ok jc blueline3 ; not compatible mov al,":" blueline2: stosb lodsb cmp al,1 ; end of command ? jnz blueline2 ; if not keep going until 1 is found blueline3: ; if here it's either not the same or was and have transfered to text cmp b[stage],1 ; doing stage 1 ? jz blueline4 ; then go do it cmp b[stage],2 ; doing stage 2 ? jz blueline7 ; then go do it jmp blueline9 ; else carry on blueline4: ; go on to find the definition text between 1 and 2 lodsb ; looking for 5 cmp al,2 jz blueline9x ; done so go find end and the address stosb mov b[stage],2 jmp blueline4 ; repeat for entire string blueline7: ; go on to find the definition text between 1 and 2 lodsb ; looking for 2 cmp al,2 jnz blueline7 blueline8: lodsb ; looking for 3 cmp al,3 jz blueline9x ; done so go find end and the address stosb jmp blueline8 ; repeat for entire string blueline9: lodsb ; looking for 5 cmp al,5 jnz blueline9 lodsd ; eax = address of code and esi = start of colon or 0 again jmp blueline1 blueline9x: lodsb ; looking for 5 cmp al,5 jnz blueline9x lodsd ; eax = address of code and esi = start of colon or 0 again mov d[godoit],eax ; setup the execute address mov b[stage],3 ; signals the end of this shit ; now quit out blueline_exit: ; if here then text has been set up cmp b[stage],3 jz blueline_exit1 cmp edi,bluetext ; if true then nothing found so put "error" in blue line jnz blueline_exit1 mov esi,edi ; edi already pointing to bluetext add esi,160 ; default error text is 160 chars from bluetext mov ecx,20 ; fill 80 characters rep movsd blueline_exit1: ; now quit out popad ret ;----------------------- ;on etry esi : ebp hold the addresses where the two stringslive ;and ecx = number of characters to compare blueline_cmp: push esi,ebp,ecx blueline_cmp0: mov al,b[esi] ; command heap cmp al,1 jz blueline_cmp1 ds cmp al,b[ebp] ; kbuf0 jnz blueline_cmp_no inc ebp inc esi loop blueline_cmp0 lodsb ; get next character cmp al,020 ; if a space then we have a unique positive match so go onto stage 1 jnz blueline_cmp1 cmp b[kbuf0],1 ; single command letter length ? jz blueline_cmp_yes ; if so then treat as special else no other comands are listed mov b[stage],1 ; we have a positive match of command+space so no longer have possibles so now do the expression part jmp blueline_cmp_yes blueline_cmp1: cmp al,1 ; if a 1 then we go onto stage2 jnz blueline_cmp_yes mov b[stage],2 blueline_cmp_yes: pop ecx,ebp,esi clc ; ok a match found ret ; if unique then stage is set up blueline_cmp_no: pop ecx,ebp,esi stc ; error ret ;----------------------- ;on entry only carry flag changed ; esi = first character of string to compare ; edi = first character of string to compare ; ecx = length of whats left of the the string from parameter to end in kbuf0 ; carry set=error clear ok general_cmp: push eax,esi,edi,ecx general_cmp1: lodsb cmp al,b[edi] ; the same ? jnz general_cmp2 ; eax already = 0 = no such command error. so just exit inc edi loop general_cmp1 ; carry on comparing clc general_cmp_exit: pop ecx,edi,esi,eax ret general_cmp2: ; if here then esi = 1st character in command heap, edi = first character of command in kbuf0, ecx = chars left stc jmp general_cmp_exit ;---------------------------------------------------------------------------- blueline_paint: ; put kbuf string into van? window and put van window onto screen pushad ; else we must be doing stage 0 or stage 1 mov es,w[sel_b800] mov ecx,80 ; 20*4 = 80 characters to delete mov esi,bluetext mov edi,49*160 mov ah,030 ; cyan background colour call blueline_paint1 ; output string ;****************** draw cursor mov ax,0200 ;set cursor mov bx,0 ;page number mov dh,b[cursor] ;line number (0 to 10) 01303 ;03,19 pos for cursor add dh,b[van4] ;makes a max of 50 mov dl,b[kbuf0] ;x pos of cursor inc dl int 010 ;****************** draw text buffer movzx ecx,b[kbuf0] ; number of characters in buffer xor eax,eax mov al,b[cursor] ; cursor y pos (0 to max lines) add al,b[van4] ; add on offset to start of command line box mov edi,eax ; copy to edi, so mull returns in edi call mull_160 ;add edi,2 mov esi,kbuf0+1 mov ah,b[colour1+2] mov al,"" stosw call blueline_paint1 mov al,020 stosw stosw ; now do two spaces 1 for cursor and other to overwrite if del was pressed ;*********** the end ! mov es,ds popad ret blueline_paint1: or ecx,ecx jz ret lodsb stosw loop blueline_paint1 ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;navigation control ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл curup: mov ax,w[_ip] ; increment the ip (it allways holds the address of the next instruction dec ax jmp updown ; finnish off ip curdown: mov ax,w[_ip] ; increment the ip (it allways holds the address of the next instruction inc ax jmp updown ; finnish off ip ;---------- shcurup: mov al,b[van9-1] ; dec the van9 window pointer dec al cmp al,0ff jz long start mov b[van9-1],al ; update ptr jmp start shcurdown: mov bx,w[van3+4] ; get number of file register lines being drawn inc bx ; we know why ! add bl,b[van9-1] ; this value must be less than total files cmp bl,b[van9-2] ; compare with total files jae long start ; if above or equal then quit inc b[van9-1] jmp start ;---------- pageup: mov ax,w[_ip] ; increment the ip (it allways holds the address of the next instruction sub ax,w[van3+4] dec ax jmp updown ; finnish off ip pagedn: mov ax,w[_ip] ; increment the ip (it allways holds the address of the next instruction add ax,w[van3+4] inc ax jmp updown ; finnish off ip ;---------- shpageup: call shpageup_ret ; this call rets jmp start ; this jmps to start shpagedn: call shpagedn_ret ; this call rets jmp start shpageup_ret: movzx ax,b[van9-1] ; sub ax,w[van3+4] jbe shpageup_ret1 dec al mov b[van9-1],al ; update ptr ret shpageup_ret1: mov b[van9-1],0 ; set to zero ret shpagedn_ret: mov bx,w[van3+4] ; get number of file register lines being drawn inc bx ; we know why ! sal bx,1 ; * 2 cos well be adding to it in a minute add bl,b[van9-1] ; this value must be less than total files cmp bl,b[van9-2] ; compare with total files jae shpagedn_ret1 ; if above or equal then set to max mov bx,w[van3+4] inc bl add b[van9-1],bl ret shpagedn_ret1: movzx ax,b[van9-2] ; get total files sub ax,w[van3+4] dec ax mov b[van9-1],al ; set to max ret ;---------- ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;screen related routines. fill,draw then paint ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;1. Fill relevent VAN windows, specific ones are done by the main engine ;2. Stitch the VAN windows into the virtual screen. ;3. Stitch the virtual screen onto the vga ;4. Phewww ! do_screen: ; call prep_file_reg ; same as fill_file_reg but done by engine which is unique call fill_file_reg ; same as prep_file_reg but done by header which is common to all. ie file registers / code window call draw_windows ; draw all the windows call paint_windows ; put em on the screen ret ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;converts text to colour:text ready for direct output to VGA ;*vscreen* *VGA* ;code window watch window ;status window eprom window ;watch window code window ;eprom window status window ;command window command window draw_windows: ; draw the vscreen ready to be pasted to the VGA mov edi,VSCREEN ; clear the vscreen with white spaces mov ecx,8000 ; 8k of screen mov ax,0720 ; white space rep stosw ; do it ; now draw the van boxes ; ****** O P C O D E W I N D O W 1 ****** mov cx,w[van3+4] ; number of screen lines inc cx ; always one more than it says, stops infinite loops mov bx,40 ; always 40 characters per line mov esi,XVAN3 ; where it is found mov edi,VSCREEN ; where it is to go call draw_vscreen ; virtual print it cmp b[twf],1 ; dual window ? jnz draw_windows1 ; if not then we have done enough else ; ****** O P C O D E W I N D O W 2 ****** mov cx,w[van3+4] ; number of screen lines inc cx mov bx,40 ; always 40 characters per line mov edi,VSCREEN+80 ; where it is to go ie 0.5 across screen call draw_vscreen ; virtual print it sub edi,80 draw_windows1: ; ****** S T A T U S W I N D O W ****** mov cx,4 ; always 4 lines mov bx,40 ; always 40 characters per line movzx edi,w[van3+4] ; inc edi ; call mull_160 ; on exit edi = edi * 160 add edi,VSCREEN ; mov d[vscr_st],edi ; store this for later mov esi,van1 ; where it is found call draw_vscreen ; virtual print it mov d[vscr_st+4],edi ; store this for later ; ****** W A T C H W I N D O W ****** mov cx,9 ; 9 lines 8 + 1 for sp -- ---- ---- ---- etc mov bx,80 ; aux windows,,, 80 chars movzx edi,w[van3+4] ; get code lines inc edi ; you know why add edi,4 ; add on status lines call mull_160 ; on exit edi = edi * 160 add edi,VSCREEN mov d[vscr_ww],edi ; store this for later mov esi,van8 ; where it is found call draw_vscreen ; virtual print it ** 9 LINES ** mov d[vscr_ww+4],edi ; store this for later mov d[vscr_ew+4],edi ; store this for later mov d[vscr_ew],edi ; store this for later incase no eprom window available which will leave these values as zero whis wrong ! ; ****** E P R O M W I N D O W ****** movzx ecx,w[van2] ; get total number of lines that show every memory address or ecx,ecx ; eprom available on this device jz draw_windows2 ; if not then skip this shit mov cx,w[van2+4] ; get selected display lines mov bx,80 ; aux windows,,, 80 chars movzx edi,w[van3+4] ; get code lines inc edi ; you know why add edi,4+9 ; add on status lines and watch lines call mull_160 add edi,VSCREEN mov d[vscr_ew],edi ; store this for later mov esi,XVAN2 ; where the text is stored call draw_vscreen ; virtual print it mov d[vscr_ew+4],edi ; store this for later draw_windows2: ; ****** F I L E W I N D O W ****** cmp b[twf],01 ; dual oppcodes already displayed jz long draw_windows3 ; if so then don't display the file registers, go onto cli call fsrbank ; prepare the starting address using the bank value mov cx,w[van3+4] ; 16 lines of file registers (should be same as opcode lines) inc cx ; 0f = 16 lines so inc 0f to 010 mov bx,36 ; file register van9 is 36 chars per line mov edi,VSCREEN+80 ; where it is to go 0.5 across screen call draw_vscreen ; virtual print it draw_windows3: ; ****** C O M M A N D L I N E W I N D O W ****** mov cx,40 ; 40 lines, this the max we will ever need ! mov bx,80 ; cli window mov esi,CLIBUFF ; the start of the text buffer area add esi,d[cli_top] ; offset to first character on specified line mov edi,d[vscr_ew+4] ; address in vscreen where it is to go call draw_vscreen ; virtual print it ret ;on entry edi = nol ;on exit edi = number of bytes mull_160: mov esi,edi sal esi,5 ; x * 32 sal edi,7 ; x * 128, 128 + 32 = 160 add edi,esi ; edi = nol * 160 ret ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;ok now put the vscreen onto the VGA ; ;*vscreen* *VGA* ;code window watch window ;status window eprom window ;watch window code window ;eprom window status window paint_windows: mov b[greenln],0 ; special green line counter mov edi,0 ; top of vga to start with mov es,w[sel_b800] ; we all know what this is by now ! ; ************************** ; * W A T C H W I N D O W * top line ; ************************** mov esi,d[vscr_ww] ; point to first line of watch window (default prog mem) mov ecx,160 ; xfer just the program memory line rep movsb ; esi and edi now ready for first line of watch stuff push esi ; save this as esi + 9 lines = stack window ! movzx ecx,b[van8-1] ; number of lines in watch window 0 to 7 and cl,07 or cl,cl jz skipit ; if zero then skip else we get loop of 0ffffffff push edi,esi ; save these as mull routines destroys these mov edi,ecx ; edi = number of lines 1 to 7 call mull_160 ; edi = edi * 160 mov ecx,edi ; ecx = total bytes from top to bottom of command window pop esi,edi ; restore these rep movsb skipit: pop esi ; now do the sp: 00 ---- ---- --- STACK LINE add esi,7*160 mov ecx,160 rep movsb ; transfer the stack call green_line ; *************************** cmp w[van2+4],0 ; * E P R O M W I N D O W * jz paint_skip0 ; *************************** sub edi,32+12 mov ecx,10 mov al,030 greendec: stosb inc edi inc al loop greendec mov ecx,6 mov al,"A" greenhex: stosb inc al inc edi loop greenhex add edi,12 mov esi,d[vscr_ew] ; start address mov ecx,d[vscr_ew+4] ; end address sub ecx,esi ; number of bytes to xfer jz paint_skip0 ; no eprom rep movsb ; transfer the eprom call green_line ; ************************ ; * C O D E W I N D O W * paint_skip0: ; ************************ mov ecx,d[vscr_st] ; end address of code window is the same as start address of status window mov esi,VSCREEN sub ecx,esi ; number of bytes to xfer rep movsb ; do it call green_line ; **************************** ; * S T A T U S W I N D O W * ; **************************** mov esi,d[vscr_st] ; start address mov ecx,d[vscr_st+4] ; end address sub ecx,esi ; number of bytes to xfer rep movsb ; do it call green_line ; ******************************* ; * C O M M A N D W I N D O W * ; ******************************* mov esi,d[vscr_ew+4] ; start address in vscreen where text starts mov ecx,49*160 sub ecx,edi rep movsb ; do it call markers ; red green markers for start/end of the command window mov es,ds ; put es back ret ; oooooh finnished at last green_line: inc b[greenln] ; special green line counter mov al,"Ф" ; the line mov ah,b[colour1] ; green line mov cl,80 ; ecx is already zero so just do cl saves opcode space rep stosw ; do it ret getused_l: ; on exit ax = number of lines used upto the cli window movzx ax,b[van8-1] and al,07 ;watch window lines 0-7 inc ax ;top line inc ax ;stack line add ax,w[van2+4] ;eprom window lines add ax,w[van3+4] ;code window inc ax ;you know why add ax,4 ;status window add al,b[greenln] ;green lines mov b[do_help-1],48 sub b[do_help-1],al ret markers: ; on entry EDI is pointing to first byte beyond the VGA test b[turbo],1 ; turbo mode ? jnz markers1 ; don't do green sub edi,2 ; do green mov ax,02efe ; our little to mark the bottom right of the command window stosw ; marker for start of last displayed line on screen! markers1: call getused_l ; on exit ax = number of lines left in cli window mov w[van4],ax ;top of command window in lines on vga mov cx,48 ;48 means 0 to 48 = 49 lines of VGA, the next line is the blue line sub cx,ax ;how many lines left mov w[van4+4],cx ;store it xor edi,edi mov di,ax call mull_160 add edi,158 ;this one works ok !!!!!! test b[turbo],1 ;turbo jz ret mov ax,04efe ; warning stosw ret ;----------------------------------------------------------------------------- ;on entry cx = number of lines ; esi = source address of text ; edi = destination address of text ; bx = Characters Per Line ; ;on exit edi = address of next contiguous location draw_vscreen: mov ah,b[colour1+3] ; get default colour scheme or cx,cx jz ret ror ecx,010 mov cx,bx draw_vscreen1: lodsb cmp al,"" ; is it a bpx ? jnz draw_vscreen1a ; mov ah,b[colour1+1] ; get bpx colour stosw ; make it red mov ah,b[colour1+3] ; get default colour scheme jmp draw_vscreen3 draw_vscreen1a: cmp al,"ў" ; is it the help point jz draw_vscreen2 ; don't mess with colour just print as normal mov dl,al and dl,0f0 cmp dl,0f0 ; is it special colour ? jnz draw_vscreen1b ; if not just print the char and carry on and al,0f ; mask of the colour mov ah,al ; set the colour to the high nybble mov al,020 ; turn into space jmp draw_vscreen2 draw_vscreen1b: cmp al,"." ; is it a dot ? jnz draw_vscreen2 ; go back to start of line and paint it red ! mov ah,b[colour1+3] ; get default colour scheme draw_vscreen2: ; just do a normal white char stosw draw_vscreen3: dec cx or cx,cx jnz draw_vscreen1 add edi,160 ; point to next line mov cx,bx sal cx,1 sub di,cx ror ecx,010 dec cx or cx,cx jnz draw_vscreen ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;fill VAN? routines ready for vscreen drawing ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;fills van9 (FILE WINDOW) with the hex-bin ;fills van3 (CODE WINDOW) with mnemonics ;FILLS van8 (WATCH WINDOW) with default stack fill_file_reg: ; get the 16 bit values and convert to hex/bin strings mov edi,van9 ; now transfer the file registers mov esi,_indf ; this file register 0 mov cx,w[van9-6] ; cx is setup by the call to prep_file_reg fill_file_reg1: add di,23 ; point to hex mov al,b[si] call convert_8k ; do HEX stosw add di,2 lodsb call convert_bin ; do BIN dec cx or cx,cx jnz fill_file_reg1 ; repeat until done ;watch window mov edi,van8 ;this bit does to look at program memory from ip movzx esi,w[_ip] mov ax,si sal esi,1 add esi,pic_mem mov cx,10 push esi call convert_16k ; do the address stosd mov ax,02020 mov al,":" stosw ; do the spaces fill_file_reg2: lodsw call convert_16k stosd inc edi dec cx or cx,cx jnz fill_file_reg2 add edi,2 pop esi mov ecx,10 fill_file_reg2a: ;now do the ascii lodsw ;do filtering and ah,b[ascii] ;if set to ff no change, if set to 020 becomes a space ror ax,8 call maskascii ;on entry al = ascii on exit al = changed ascii, ah unchanged ror ax,8 call maskascii stosw loop fill_file_reg2a ;code window ;calculates IP with current altip and NOL to ensure that when ALTIP runs ;IP will show up somewhere on the screen ;starting @ _altip to _altip+NOL (uses _ip which is restored afterwards) call get_altip ; get the starting address for code window mov bp,0 ; yes we want to display the decoded string. mov cx,w[_ip] ; we must save this mov w[_iptmp],cx ; temp storage mov cx,w[_altip] ; get the starting address mov w[_ip],cx ; put into ip (we will restore this at the end) mov bx,w[van3+4] ; number of lines on sceen inc bx mov cl,b[twf] ; if 2 columns exist then NOL does not equal number of disassembled mnemonics !! shl bx,cl ; if 0 then nothin happens, NOL same as displayed NOL but if 2 columns are present twf = 1 then NOL = NOL * 2 mov cx,bx ; this does number of lines from cursor to end of van3, mov edi,XVAN3 ; pointer to van3 in extended memory call get_symbols ; fill with if cod file present (code symbols or offset by 12) else no offset fill_file_reg3: ; now loop from NOL to zero push cx,edi ; save xvan3 pointer call decodepic ; xfer mnemonic string and set up variables for simpic movzx esi,di ; get last byte pos inside PSP 080 sub esi,080 ; get rid of displacement mov ecx,esi ; this is how many chars to copy for the line mov esi,080 ; ds:esi point to start mov edx,40 ; 80 chars per line sub edx,ecx ; now loop + edx = 80 characters per line ! plenty of room. only forty are used on screen !!!!! pop edi ; get pointer for van3 movsd ; transfer address sub ecx,4 ; adjust loop for movsd lodsw ; get the two spaces after the address. decodepic will set bit 7 if a bpx was found, and correctly display the right opcode mov bx,w[_ip] ; the current IP adress cmp bx,w[_iptmp] ; is it where the cursor should be ? jnz fill_file_reg3b ; if not then carry on and leave ax as two spaces mov al,"#" ; else set to a hash to be drawn, remember bit 7 for bpx fill_file_reg3b: ; we could now check for bpx stosw ; store attribute and space, attribute either a space, space+bpx, space+hash, hash+bpx dec ecx dec ecx ; adjust loop for stosw rep movsb ; xfer the rest of the string mov al,020 ; spaces mov ecx,edx ; clear rest of line rep stosb ; and start at the next line pop cx ; get outer loop inc w[_ip] call wrap_ip ; done by engine, wrap arround each device is different dec cx or cx,cx jnz fill_file_reg3 ; repeat line mov cx,w[_iptmp] ; restore IP cos we messed with it mov w[_ip],cx ret ; all done maskascii: cmp b[ascii+1],1 ; want to mask this stuff jnz ret cmp al,33 jb maskascii_dot cmp al,127 ja maskascii_dot ret ; nothing is changed maskascii_dot: mov al,"." ; this is maximum of 0ef as f0-ff are 15 colours ret ;on entry nothing ;on exit ALTIP is set to a sensible value depending on NOL and IP get_altip: ; code window start address call wrap_ip ; done by engine, wrap arround each device is different mov ax,w[_ip] ; get current ip mov bx,w[van3+4] ; get NOL inc bx ; 0 to f = 16 lines so inc mov cl,b[twf] ; if 2 columns exist then NOL does not equal number of disassembled mnemonics !! shl bx,cl ; if 0 then nothin happens, NOL same as displayed NOL but if 2 columns are present twf = 1 then NOL = NOL * 2 cmp ax,w[_altip] ; compare IP with current ALTIP jae get_altip_above ; IP is above or equall to ALTIP but is it within code window or ax,ax jz get_altip_store sub ax,bx ; make altip = IP - 1 so that one instruction is above the hash cursor inc ax get_altip_store: ; if here ax is either already zero or has just been equal to IP - 1 mov w[_altip],ax ; store this call wrap_ip ret ; quit out now it's all done get_altip_above: ; IP is above ALTIP but is it within the code window add bx,w[_altip] ; get the end of the code window cmp ax,bx ; this must be below or equal to be ok ! jb ret ; if it is then quit out jmp get_altip_store ; store it and quit ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;get command line parameters and xfer filename to pic_mem ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;------------------ ------------------ ------------------ ------------------ ---- getfile: call message3 cld mov esi,080 mov edi,pic_mem+PICMEM lodsb movzx ecx,al ; number of characters in command line or ecx,ecx jz getfile_err ; no filename getfile1: lodsb ; get first character cmp al,020 ; is it a space loopz getfile1 ; strip out spaces jecxz getfile_err ; not enough filename info getfile2: stosb ; store first character into asciiz1 lodsb ; get the next cmp al,02e ; is it a dot ? loopnz getfile2 jecxz getfile_err ; no dot in file name stosb ; store the dot push edi ; save address of dot rep movsb xor al,al stosb ; zero terminated mov esi,pic_mem+PICMEM ; get filtered file name mov edi,080 ; replace original with tidied up string movsd movsd movsd pop edi sub edi,pic_mem+PICMEM ; add edi,080 mov d[edi],0646f63 ; turn from hex to cod, zero terminated clc ; file ok ret getfile_err: mov ax,1 ; error for bad getfile routine jmp badexit ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;Load file f1handle: dw 0 ;file handle loadfile: mov edx,pic_mem+PICMEM ; address of file name mov ecx,0 ; normal file mov ax,03d00 int 021 ; open file jc loadfile_err mov bx,ax ; bx=handle mov w[f1handle],ax ; save handle mov edx,pic_mem+PICMEM ; 1 meg on from eocp mov eax,03f00 ; read file movzx ebx,w[f1handle] mov ecx,0ffffff ; 1 MEG max to load int 021 jc loadfile_err mov edi,edx ; point to start of file add edi,eax ; add number of bytes loaded xor eax,eax mov d[edi],eax ; terminate file with 0 inc edi inc edi inc edi inc edi mov eax,03e00 movzx ebx,w[f1handle] int 021 ; close data file clc ret loadfile_err: mov eax,2 jmp badexit ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;Load cod file ;get symbols and store into van2 loadcodfile: push esi,edi mov esi,080 mov edi,pic_mem+PICMEM ; address of file mov edx,edi ; we need this for dos call cld movsd movsd movsd ; copy the filename.cod pop edi,esi mov ecx,0 ; normal file mov ax,03d00 int 021 ; open cod file jc loadcodfile_err mov bx,ax ; bx=handle mov w[f1handle],ax ; save handle mov edx,pic_mem+PICMEM ; 1 meg on from eocp mov eax,03f00 ; read file movzx ebx,w[f1handle] mov ecx,0ffffff ; 1 MEG max to load int 021 jc loadfile_err mov edi,edx ; point to start of file add edi,eax ; add number of bytes loaded push eax xor eax,eax mov d[edi],eax ; terminate file with 0 inc edi inc edi inc edi inc edi mov eax,03e00 movzx ebx,w[f1handle] int 021 ; close data file mov b[codfile],1 ; set to cod file loaded pop ecx ; get bytes in codfile clc ret loadcodfile_err: mov b[codfile],0 ;set to no symbols loaded ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Strip codfile rountine ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;------------------ ------------------ ------------------ ------------------ ---- ; cod_strip: db 0 ; length of string dd 0 ; source get_fishy: call get_code ; get the labels for runtime code ret ;scan for first instance of __ go back three copy target pic to get_code: mov esi,pic_mem+PICMEM mov edx,ecx ; save precious counter (length of cod file) @get_code1: lodsb ; looking for __ cmp al,"_" jnz @get_code2 lodsb cmp al,"_" jz @get_code3 @get_code2: loopnz @get_code1 mov b[codfile],0 ; cod file is bad ; we need to report that cod file is no good stc ret @get_code3: ; if here we havefound double __ mov edi,codfile+1 ; point to data block dec esi dec esi dec esi lodsb ; get length of text mov edx,esi ; we need this later movzx ecx,al rep movsb mov al,"$" stosb mov al,0 stosb ; zero terminate, all done. Now do labels @get_code4: mov esi,edx ; restore beginning of symbols __ add esi,12 ; point to info ??? inc esi inc esi inc esi lodsb ; get length of file label mov b[cod_strip],al mov d[cod_strip+1],esi ; now pointing to begin of text so save it add esi,12 lodsb ; this is a marker '/' and should be present if a valid label cmp al,02f ; if not 02f then it could be a jmp label jz @get_code5 ; this is a marker 'M' and should be present if a valid jmp label cmp al,02e ; if not 02e then it could be something else jz @get_code6 ret ;---------------------- ; fill file registers ; with labels marked 2f @get_code5: ; store file register variable xor eax,eax lodsw ; get the file register sal eax,2 ; * 4 mov edi,eax sal eax,3 ; * 32 add edi,eax ; * 36 (align each entry) add edi,van9+3 ; offset past the 3 digit and point to space mov al,b[colour1+4] ; this is marked for colour stosb ; store it movzx ecx,b[cod_strip] mov esi,d[cod_strip+1] ; now pointing to begin of text mov edx,esi rep movsb ; transfer the rest of the file symbol jmp @get_code4 ;---------------------- ; fill code window ; with labels marked 2f @get_code6: ; store file register variable xor eax,eax lodsw ; get the file register sal eax,2 ; * 4 mov edi,eax sal eax,3 ; * 32 add edi,eax ; * 36 (align each entry) add edi,van9+4 ; offset past the 3 digit number and space movzx ecx,b[cod_strip] mov esi,d[cod_strip+1] ; now pointing to begin of text mov edx,esi rep lodsb ; move pointer onwards jmp @get_code4 ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Shrink it rountine ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;------------------ ------------------ ------------------ ------------------ ---- ;format of hex file. ; :010203040506070809 ; : start of the string ; 01 Number of entries ; 0203 start address for this line ; 04 String command 0=store 1=end of code ; 0506 opcode ; 07 CRC shrinkit: mov esi,pic_mem+PICMEM shrinkit1: lodsb ; get the hex ascii or al,al jz shrinkit_exit ; ahh finnished, sort out the start , end locations cmp al,":" ; start of line ? jz shrinkit2 cmp al,0d ; end of line ? jnz shrinkit1 ; repeat until something crops up lodsb ; next char cmp al,0a ; is it 0d,0a jz shrinkit1 ; keep looking for a colon jmp shrinkit_err ; lines not terminated with 0d,0a shrinkit2: ; if here then we have a starting line lodsw ; number of entries in this line call convert_hex ; eax ascii becomes ax binary mov cx,ax ; setup our loop xor ch,ch ; clear high byte of loop shr cx,1 ; bytes become words or cx,cx jcxz shrinkit_exit ; end of code, next byte is a zero or should be lodsd ; get start address ror eax,010 call convert_hex add esi,2 ; skip file command (00 = store code) 01 = end of code movzx edi,ax add edi,pic_mem shrinkit3: push cx ; save the counter lodsd ; get first oppcode call convert_hex ; eax ascii becomes ax binary stosw pop cx ; pop count dec cx or cx,cx jnz shrinkit3 ; repeat line lodsw ; get the checksum jmp shrinkit1 ; repeat until 0 is found EOF shrinkit_exit: ;we must set up the start and end pointer call shrinkit_getfuse ; on exit ax = fuses mov w[fuses],ax ; configuration mov w[_config],ax ; copy to simpic ret shrinkit_err: mov ax,3 jmp badexit ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;Update routines message2: pushad mov ax,0900 mov edx,msg02 int 021 popad ret message3: pushad mov ax,0900 mov edx,msg03 int 021 popad ret msg02: db "Reading contents of PIC chip",0d,0a,"$" msg03: db "Loading hex file",0d,0a,"$" ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;exit routines goodexit: mov ax,3 int 010 mov ax,04c00 int 021 badexit_err: db "Error. ---- ",0d,0a,"See manual for help with this program ",0d,0a,"$" badexit: call convert_16k mov d[badexit_err+7],eax ;put err code into string mov ax,3 int 010 mov ax,0900 mov edx,badexit_err int 021 ; stdout mov ah,04c ; al already setup int 021 fatal_error: ; if here we have big problems so exit with code mov eax,ebp ; transfer error code jmp badexit ; straight to DOS ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Timer delay routines ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;------------------ ------------------ ------------------ ------------------ ---- wait_tmr: ; 100 us ror ecx,010 ror eax,010 mov cx,w[tmr] wait_tmr1: pushad popad dec cx or cx,cx jnz wait_tmr1 ror ecx,010 ror eax,010 ret ;------------------ ------------------ ------------------ ------------------ ---- wait_ltmr: push cx,ax mov cx,1000 ; wait 1000*1000 100us = 1 second wait_ltmr1: call wait1ms_tmr dec cx or cx,cx jnz wait_ltmr1 pop ax,cx ret ;------------------ ------------------ ------------------ ------------------ ---- wait1ms_tmr: push cx,ax mov cx,0120 ; 1ms wait1ms_tmr1: call wait_tmr dec cx or cx,cx jnz wait1ms_tmr1 pop ax,cx ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Programmer hardware control routines ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;---------------------------------------------------------------------------- powerup: call powerdown call vddon call reset ret ;---------------------------------------------------------------------------- powerdown: mov bh,0c ; start bh off with default call clklow call dtalow call vddoff call vppoff ret ;---------------------------------------------------------------------------- reset: call vppoff call clklow call dtalow call vppon call wait_ltmr ret ;---------------------------------------------------------------------------- vppoff: mov dx,w[prntrprt] ; 378 write data pin or bh,08 and bh,0ef mov al,bh out dx,al ret ;---------------------------------------------------------------------------- vppon: mov dx,w[prntrprt] ; 378 write data pin and bh,0f7 ; vdd = on or bh,010 mov al,bh out dx,al ret ; note vdd must be on to enter vpp ;---------------------------------------------------------------------------- vddoff: mov dx,w[prntrprt] ; 378 write data pin or bh,04 mov al,bh out dx,al ret ;---------------------------------------------------------------------------- vddon: mov dx,w[prntrprt] ; 378 write data pin and bh,11111011b mov al,bh out dx,al ret ;---------------------------------------------------------------------------- clklow: mov dx,w[prntrprt] ; 378 write data pin and bh,0fd ; clear bit 2 gp1 mov al,bh out dx,al call wait_tmr ret ;---------------------------------------------------------------------------- clkhigh: mov dx,w[prntrprt] ; 378 write data pin or bh,2 ; set bit 2 gp1 mov al,bh out dx,al call wait_tmr ret ;---------------------------------------------------------------------------- dtahigh: call wait_tmr mov dx,w[prntrprt] ; 378 write data pin or bh,1 ; set bit 0 gp0 = 5v mov al,bh out dx,al call wait_tmr ret ;---------------------------------------------------------------------------- dtalow: call wait_tmr mov dx,w[prntrprt] ; 378 write data pin and bh,0fe ; clear bit 0 gp0 = 0v mov al,bh out dx,al call wait_tmr ret ;---------------------------------------------------------------------------- dtatri: call dtahigh ret ;---------------------------------------------------------------------------- dtaread: call wait_tmr call wait_tmr call wait_tmr call wait_tmr call wait_tmr call wait_tmr mov dx,w[prntrprt] inc dx in al,dx rol al,2 and al,1 ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;Converter routines ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;------------------ ------------------ ------------------ ----------------- ;on entry ax=oppcode ;on exit ax=ascii value or last two digits of label ;only ax is used convert_3f: and al,07 ; mask out 3 lsb add al,030 ; convert to ascii ret convert_5f: and al,01f ; mask out 5 bits mov ah,al ; copy shr al,4 ; get left nibble and ah,0f ; mask right nible add ah,030 ; convert to ascii add al,030 ; convert to ascii cmp ah,039 ; less than nine ? jbe ret add ah,7 ; convert to hex letters ret convert_7f: and al,07f ; mask out 7 bits mov ah,al ; copy shr al,4 ; get left nibble and ah,0f ; mask right nible add ah,030 ; convert to ascii add al,030 ; convert to ascii cmp ah,039 ; less than nine ? jbe ret add ah,7 ; convert to hex letters ret convert_8k: mov ah,al ; copy shr al,4 ; get left nibble and ah,0f ; mask right nible add ah,030 ; convert to ascii cmp ah,039 jbe convert_8ka add ah,7 convert_8ka: add al,030 ; convert to ascii cmp al,039 ; less than nine ? jbe ret add al,7 ; convert to hex letters ret convert_16k: ; converts ax into eax ascii push ax call convert_8k ror eax,010 pop ax xchg ah,al call convert_8k ret convert_hex: ; eax holds 4 digit ascii codes push cx,ebx mov cx,4 xchg ah,al ror eax,010 xchg ah,al convert_hex1: mov bh,al sub bh,030 cmp bh,0f jbe convert_hex2 sub bh,7 ; bloody ascii values convert_hex2: ror ebx,4 ror eax,8 dec cx or cx,cx jnz convert_hex1 rol ebx,8 mov ah,bl mov al,bh ; swap em round pop ebx,cx ret ; now ax holds real value convert_bin: ; eax holds 4 digit ascii codes push bx,ax,cx mov bl,al mov cx,8 convert_bin1: mov al,030 ; ready to store a zero rcl bl,1 jnc convert_bin2 mov al,031 ; change it to a 1 convert_bin2: stosb cmp cx,5 jnz convert_bin3 add di,1 convert_bin3: dec cx or cx,cx jnz convert_bin1 pop cx,ax,bx ret cnvrt_rdx_32: ; output 32 bit value, using radix bit to do dec or hex test b[turbo],020 ; radix ? jz cnvrt_rdx_32hex ; go do hex else push ebx mov bl,10 ; do ten digit decimal value call convert_dec pop ebx ret cnvrt_rdx_32hex: ; go do hex push eax rol eax,010 call convert_16k stosd pop eax call convert_16k stosd mov ax,02020 stosw ret cnvrt_rdx_16: ; output 32 bit value, using radix bit to do dec or hex movzx eax,ax test b[turbo],020 ; radix ? jz cnvrt_rdx_16hex ; go do hex else push ebx mov bl,5 ; do ten digit decimal value call convert_dec pop ebx ret cnvrt_rdx_16hex: ; go do hex call convert_16k stosd mov ax,02020 stosw ret ;мммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммммм ;convert bewteen ;on entry edi = address of digits ; eax = 32 bit number to convert convert_dec: push ebp,eax,ebx,ecx,edx,edi dec edi ;always 1 character out movzx ecx,bl ;get number of digits mov ebp,ecx add edi,ecx ;point to units column mov ebx,0a ;divisor mov si,0 convert_dec1: inc si cmp si,4 jnz convert_dec0 xor si,si inc si mov b[edi],"," dec edi convert_dec0: xor edx,edx ;clear it first div ebx ;divide it edx:eax / 10, eax=answer, edx=left over add dl,030 ;turn into ascii mov b[edi],dl ;store it dec edi ;go back or eax,eax ;set flags loopnz convert_dec1 ;if eax=0 then sum is finished or eax,eax ;if not zero then err jnz convert_dec7 or ecx,ecx ;check it again jz convert_dec9 ;don't pad out if all digits were done mov al,020 ;space convert_dec2: mov b[edi],al ;pad out with spaces dec edi loop convert_dec2 ;for the rest jmp convert_dec9 ;quit out convert_dec7: ;if here put the word error in the text convert_dec8: mov b[edi],"x" dec edi,1 loop convert_dec8 ;fill the doofer convert_dec9: pop edi,edx,ecx,ebx,eax add edi,ebp pop ebp ret ;version details add to HEADER.32 before assembling abouttext: db ".com ў 32 Bit DPM runtime. (c) 2001 - 2007 by Graham Medland.$$" db "Ver [ 1.00 ] s/n [ 031207BETA126 ] ",0f4,"[ *-=-_B_E_T_A_-=-* ] $" db "email: gm236 @ exeter.ac.uk$" db "$Get the latest version FREE from www.vent-clenz.co.uk/pic/$",0 hotkeytext: db "F1 Single step following normal instruction flow$" db "F2 Same as F1 but call routines are executed in one go$" db "F3 Repeat last command line entry$" db "F4 Single step with non sticky breakpoint at ip+1$" db "F5 Same as F4 but trap at ip+2$" db " F4,F5 used mainly with skip instructions$" db "F10 Toggle between secondary code window and file window$",0 ;************************** ;* 12c508 32bit! * ;************************** ;Mem map ; ; ; ; ; ;0xxx crap ;0440 End of bootstrap ;0404 Start of bootstarp ;0403 ID ;0402 ID ;0401 ID ;0400 ID ;01ff OSCALL ;01fe top of RAM ;0000 start of RAM wrapindf: dd 01f ; max allowed wrapmem: dd 0fff ; max allowed wrap_ip: ; used by header.32 to wrap the IP during paint code window and w[_ip],0fff ;this is the max allowed and w[_altip],0fff ;this is the max allowed ret updown: ;finnish off ip and ax,0fff ;this is the maximum value allowed 0 to 4095 (although the pic ip can only reach 0-1023 the program/verufy mode allows 0 to 4095) mov w[_ip],ax ;update ip pointer mov b[_pcl],al jmp start ;---------------------------------------------------------------------------- do_ssf1: ; do single step call fastdecode call simpic jmp start ; inc ip and do all the other stuff do_msf2: movzx esi,w[_ip] ;get the address sal esi,1 ;word align add esi,pic_mem ;offset lodsw ; get the oppcode cmp ah,09 ; is it a call instruction jnz do_ssf1 ; if not do a single step mov ax,w[_ip] ; get the current ip inc ax ; this is our stop point mov w[_brk],ax ; break now holds the next address call get_time ; stores the current time and resets the ebp counter do_msf2a: call fastdecode ;decode the current instruction mov ax,w[_brk] ; get the break address cmp ax,w[_ip] ; do we break out ? jz long breakpoint ; break out call simpic ; simulate it, skip zero may have incremented it already test b[turbo],1 jnz do_msf2a ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_msf2a ; if not keep going until original ip+1 is reached do_msf4: movzx esi,w[_ip] ; get the address sal esi,1 ;word align add esi,pic_mem ;offset lodsw ; get the oppcode cmp ah,09 ; 1001 kkkk kkkk CALL jz do_msf2 ; if so do multi step +1 and ax,0fc0 cmp ax,02c0 ; 0010 11df ffff DECFSZ jz do_msf4a ; if so do multi step +2 cmp ax,03c0 ; 0011 11df ffff INCFSZ jz do_msf4a ; if so do multi step +2 cmp ah,06 ; 0110 bbbf ffff BTFSC jz do_msf4a ; if so do multi step +2 cmp ah,07 ; 0111 bbbf ffff BTFSS jz do_msf4a ; if so do multi step +2 jmp do_ssf1 ; else just do a simple single step do_msf4a: mov ax,w[_ip] ; get the current ip inc ax ; this is our stop point inc ax ; missing the skipped instruction mov w[_brk],ax ; break now holds the next address (the one that is skipped to) call get_time ; stores the current time and resets the ebp counter do_msf4b: call fastdecode ; decode the current instruction mov ax,w[_brk] ; get the break address cmp ax,w[_ip] ; do we break out ? jz long breakpoint ; break out call simpic ; simulate it, skip zero may have incremented it already test b[turbo],1 jnz do_msf4b ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_msf4b ; if not keep going until original ip+1 is reached do_msf5: mov ax,w[_ip] ; get the current ip inc ax ; this is our stop point mov w[_brk],ax ; break now holds the next address (the one that is skipped to) call get_time ; stores the current time and resets the ebp counter do_msf5a: call fastdecode ;decode the current instruction mov ax,w[_brk] ; get the break address cmp ax,w[_ip] ; do we break out ? jz long breakpoint ;break out call simpic ; simulate it, skip zero may have incremented it already test b[turbo],1 jnz do_msf5a ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_msf5a ; if not keep going until original ip+1 is reached ;--------------------- entry point, now go do byte,word or dword routines do_mseye: ; esi = address, eax = data, ecx = data size call get_time ; stores the current time and resets the ebp counter mov cl,b[eyedata+8] cmp cl,1 ; byte ? jz do_mseye_b cmp cl,2 ; word ? jz do_mseye_w cmp cl,4 ; dword ? jz do_mseye_d do_mseye_b: ;byte check mov al,b[0] ;this address is setup by do_mseye cmp al,b[eyedata+4] ;compare jz long breakeyeb ;break out if the same !!!! call fastdecode ;decode the current instruction call simpic ;simulate it, skip zero may have incremented it already test b[turbo],1 jnz do_mseye_b ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_mseye_b ;if not keep going until original ip+1 is reached do_mseye_w: ;byte check mov ax,w[0] ;this address is setup by do_mseye cmp ax,w[eyedata+4] ;compare jz long breakeyew ;break out if the same !!!! call fastdecode ;decode the current instruction call simpic ;simulate it, skip zero may have incremented it already test b[turbo],1 jnz do_mseye_w ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_mseye_w ;if not keep going until original ip+1 is reached do_mseye_d: ;byte check mov eax,d[0] ;this address is setup by do_mseye cmp eax,d[eyedata+4] ;compare jz long breakeyed ;break out if the same !!!! call fastdecode ;decode the current instruction call simpic ;simulate it, skip zero may have incremented it already test b[turbo],1 jnz do_mseye_d ; if turbo mode on then don't scan keyboard ! in al,060 cmp al,1 jz long breakkey ;break out jmp do_mseye_d ;if not keep going until original ip+1 is reached ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;update the van1 and displays the registers @ the bottom of the screen prep_file_reg: mov edi,van1+3 mov ax,w[_w] ;get the w register call convert_8k stosw add edi,2 mov ax,w[_w] call convert_bin ;do the binary mov edi,van1+20 mov esi,van0 mov cx,8 ;8 bits to xfer mov bl,b[_status] prep_file_reg0: lodsb ;first flag bit rcl bl,1 jc $+4 ;skip the mov al,020 mov al,020 ;replace with a space stosb dec cx or cx,cx jnz prep_file_reg0 mov edi,van8+644 mov al,b[_sp] ;get the stack pointer call convert_8k stosw add edi,3 mov ax,w[_sp+1] call convert_16k stosd inc edi mov ax,w[_sp+3] call convert_16k stosd mov edi,van1+127 mov al,b[_config] call convert_8k ;do the byte stosw add edi,2 mov al,b[_config] call convert_bin ;do the binary mov edi,van1+87 mov eax,d[_fosc] ;left word call cnvrt_rdx_32 ; output 32 bit value, using radix bit to do dec or hex mov edi,van1+103 mov ax,w[_wdt] call cnvrt_rdx_16 ; output 32 bit value, using radix bit to do dec or hex mov edi,van1+47 mov al,b[_option] call convert_8k ;do the byte stosw add edi,2 mov al,b[_option] call convert_bin ;do the binary mov edi,van1+67 mov al,b[_tris] call convert_8k ;do the byte stosw add edi,2 mov al,b[_tris] call convert_bin ;do the binary ret fsrbank: ;adjusts the fsr starting number so header.32 ;works properly mov esi,van9 ;start of file register 7 movzx cx,b[van9-1] ;offset for scrolling mov ax,36 ;36 chars per line imul cx add si,ax ;true offset mov w[van9-4],si ;store true offset mov cx,16 ret pidt: db "12c508",0 ;program ID van0: db "w btpzac" ;(w) wake up (b) bank select (t) time out (p) power down (z) zero (a) digit carry (c) carry van1: db " W uu ...._.... -------- " db "option -- ...._.... tris -- ...._...." db "fosc.. -------- wdt ---- " db "config -- ...._.... " van2: dw 0,0,0 ; maximum 0 lines = 0 bytes .... max on screen 0 lines, current selecetion 0 lines ; data is stored in high mem not here use XVAN2 in the equ of header.32 van3: dw 020,32,0f ; maximum 0 lines = 0 bytes .... max on screen 0 lines, current selecetion 0 lines ; data is stored in high mem not here use XVAN3 in the equ of header.32 van4: dw 0,0,0 ; command window stuff. set up by clibox how many lines down from top of vga the cursor can start, not used , total number of lines available from van4 to bottom of screen db 070 ; maximum 7 lines .... current selection 7 lines high/low nibble van8: db " " db " " db " " db " " db " " db " " db " " db " " db " sp -- ---- ---- " dw 020 ;total number of file registers per bank dw 0 ;true offset pointer from van9 for display db 020 ;number of file registers - number of lines displayed db 0 ;index pointer for scrolling van9 window van9: db "000 indf.............. -- ...._...." db "001 tmr0.............. -- ...._...." db "002 pcl............... -- ...._...." db "003 status............ -- ...._...." db "004 fsr............... -- ...._...." db "005 osccal............ -- ...._...." db "006 gpio.............. -- ...._...." db "007 .................. -- ...._...." db "008 .................. -- ...._...." db "009 .................. -- ...._...." db "00A .................. -- ...._...." db "00B .................. -- ...._...." db "00C .................. -- ...._...." db "00D .................. -- ...._...." db "00E .................. -- ...._...." db "00F .................. -- ...._...." db "010 .................. -- ...._...." db "011 .................. -- ...._...." db "012 .................. -- ...._...." db "013 .................. -- ...._...." db "014 .................. -- ...._...." db "015 .................. -- ...._...." db "016 .................. -- ...._...." db "017 .................. -- ...._...." db "018 .................. -- ...._...." db "019 .................. -- ...._...." db "01A .................. -- ...._...." db "01B .................. -- ...._...." db "01C .................. -- ...._...." db "01D .................. -- ...._...." db "01E .................. -- ...._...." db "01F .................. -- ...._...." ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;extended help command1: ;extended help heap, specific to each device only db ":status ",1," this is the status register and contains p,z,t,g flags",2 db " this is the status register and contains p,z,t,g flags",3 db "status 4",4 db "status 5a$status5b$status5c$$",5 dd do_nothing db 0 ; terminates all help ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;initialise variables clrram: mov edi,pic_mem ;first clear the ram mov ax,0fff ;set all twelve bits to high mov ecx,4096 ;maximum ram (roll over) only 1024 bytes available rep stosw ;clear the ram ret ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;power on reset sets up the varuables/registers for this condition ;12c508 pic_por: ; checked ! mov b[_tris],03f ; --11 1111 mov b[_option],0ff ; 1111 1111 mov b[_indf],0 ; xxxx xxxx mov b[_tmr0],0 ; xxxx xxxx mov b[_pcl],0ff ; 1111 1111 mov b[_status],018 ; 0001 1xxx or b[_fsr],0e0 ; 111x xxxx mov b[_osccal],070 ; 0111 ---- mov b[_gpio],0 ; --xx xxxx mov w[_ip],01ff mov d[_fosc],0 ; clear fosc mov d[_wdtcounter],0 ; do the postscaler mov b[_sp],0 ; and stack pointer mov d[_sp+1],0 ; clear stack contents ret pic_por1: ; checked ! mov b[_tris],03f ; --11 1111 mov b[_option],0ff ; 1111 1111 mov b[_pcl],0ff ; 1111 1111 or b[_fsr],0e0 ; 111u uuuu mov w[_ip],01ff and b[_status],09f ; q00q quuu and b[_osccal],0f0 ; uuuu ---- and b[_gpio],03f ; --uu uuuu ret ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ ;simpic simulates the opp codes ;on entry pic_rout holds the opp code number ; ax holds the oppcode ;on exit all registers, flags, IP and accumulator are changed even 4 simpic_vect: dd pic_nop,pic_option,pic_sleep,pic_clrwdt,pic_clrw,pic_tris,pic_movwf dd pic_clrf,pic_subwf,pic_decf,pic_iorwf,pic_andwf,pic_xorwf,pic_addwf dd pic_movf,pic_comf,pic_incf,pic_decfsz,pic_rrf,pic_rlf,pic_swapf dd pic_incfsz,pic_bcf,pic_bsf,pic_btfsc,pic_btfss,pic_retlw,pic_call dd pic_movlw,pic_iorlw,pic_andlw,pic_xorlw,pic_goto,pic_error _brk: dw 0 ;the break address for multi step routine _flags: ;these are for dis12c to monitor how the pic behaves db 0 ;bit 0 0 = normal running ; 1 = A sleep instruction has been activated ;bit 1 0 = No lpt I/O (speeds it up) ; 1 = Yes send GPIO to lpt (3 times slower) _prescaler: db 0 ;if prescaler assignment is set then 1/1 upto 1/256 steps even 4 _sp: db 0 ;stack pointer bit 7=overflow even 4 dw 0,0 ;the only two locations allowed for the stack addresses _config: dw 0 ;the configuration bits even 4 _fosc: dd 0 ;number of internal clock oscilations 4 per instruction _wdtcounter: dd 0 ;copy of fosc which is reset each time the wdt times out even 4 _oppcode: dw 0 ;run time copy of the oppcode _iptmp: dw 0 ;temp variable for show_oppcodes _altip: dw 0 ;the starting point for show_oppcodes _ip: dw 0 ;run time copy of the pic instruction pointer _wdt: dw 0 ;16 bit counter to simulate the 18ms wdt (this is all ways running) _w: db 0 ;accumulator _tris: db 0 _option: db 0 ;these are the general file registers with the first 6 being the special ones even 4 _indf: db 0 ;memory location 0 _tmr0: db 0 ;memory location 1 _pcl: db 0 ;memory location 2 _status: db 0 ;memory location 3 _fsr: db 0 ;memory location 4 _osccal: db 0 ;memory location 5 _gpio: db 0 ;memory location 6 db 25 dup(0) ;the rest of the memory locations upto 01f ;length of string ;the string ;byte,word,dword size of variable ;dd address of variable variable: db "ip",2 dd _ip db "w",1 dd _w db "config",1 dd _config db "fosc",4 dd _fosc db "wdt",2 dd _wdt db "option",1 dd _option db "tris",1 dd _tris db "sp",1 dd _sp db "indf",1 dd _indf db "tmr0",1 dd _tmr0 db "pcl",1 dd _pcl db "status",1 dd _status db "fsr",1 dd _fsr db "osccal",1 dd _osccal db "gpio",1 dd _gpio db "flags",1 dd turbo db 0 ;marks the end of the variables ;on entry fastdecode pic has put the vector address into SI ;bx = oppcode simpic: inc ebp ; update the instruction loop counter ! ;*************************** ;read the gpio values from 877 ;*************************** call get_ports ; get data from pic DO NOT USE ESI or BX !!!!!!! ;******************* ;simulate the opcode ;******************* mov ax,bx ; get the oppcode call [esi*4+simpic_vect] ; call the routine and simulate the opcode jnc simpic1 ; if no writes to any file registers then simply skip the crap ; and update indf with the same value as b[fsr], then do fosc/wdt etc ;************************** ;check for sensitive writes ;************************** call put_ports ; put data to pic or bx,bx ; checking for indf write ? jz simpic_indfwr ; do indf write stuff else cmp bx,2 ; writing to pcl ? jnz simpic1 ; carry on as normal else if no indf then just check pcl xor ah,ah mov al,b[_pcl] mov w[_ip],ax ; reload ip with computed adress call simpic1_fosc ; add the extra fosc and carry on jmp simpic1 ; carry on as normal simpic_indfwr: ; write to indf was done so replicate to b[fsr] movzx bx,b[_fsr] ; get the address fsr points to and bx,01f ; mask 0 to 4 mov al,b[_indf] ; get the indf byte mov b[bx+_indf],al ; put the byte at this address (now check indf did not write to pcl) cmp bx,2 ; writing to pcl ? jnz simpic1a ; carry on as normal (1a does not repeat the indf update) else xor ah,ah ; clear high byte mov al,b[_pcl] mov w[_ip],ax ; reload ip with computed adress call simpic1_fosc ; add the extra fosc and carry on jmp simpic1a ;****************************************************************** ;update the indf register with b[fsr] do pcl,wdt,prescaler etc oh and fosc ;****************************************************************** simpic1: ; if here then pcl was not altered or has been updated so carry on movzx bx,b[_fsr] ; get the address fsr points to and bx,01f ; mask 0 to 4 mov al,b[bx+_indf] ; get the byte at this address (dh is not used anywhere and will be preserved] mov b[_indf],al ; put into indf (so it is now the same) simpic1a: mov ax,w[_ip] ; increment the ip (it allways holds the address of the next instruction inc ax ; inc the ip now so that address wraparround calculates corrrectly and ax,01ff mov b[_pcl],al ; put the low order bits of pcl into IP (it may have been changed), if it has then the bit 8 needs to be reset !!!! mov w[_ip],ax ; update ip with calculated page bit +8 bit value ;****************************************************************** ;update the fosc oscilator (counts in 1 steps) but is displayed as4 ;****************************************************************** call simpic1_fosc ; do the fosc oscilator (2 cycle instructions will already have inceased this by one call simpic1_t0cs ; do the timer module (counter or timer) and prescaler if assigned ! call simpic1_wdt ; do the wdt module with prescaler if assigned test b[_flags],1 ; has a SLEEP been issued ? jnz simpic3 ; if so go and do sleep shite else do wdt cmp w[_wdt],18000 ; has wdt timed out ? jb simpic2 call pic_por1 ; watch dog timeout reset and b[_status],0f ; 0000-uuuu WDT normal operation mov d[_wdtcounter],0 mov w[_wdt],0 pop eax jmp breakwdt ; and break out simpic2: test w[_config],010 ; looking for mclre jz ret ; do nothing if 0 as it's tied to Vdd call simpic_getgpio ; get the pins cmp al,04 ; pressed '3' jnz ret ; end of simpic ! pop eax ; do a reset jmp breakmclr ; master clear reset ! ret simpic3: ; if here a sleep instruction was executed and b[_flags],0fe ; clear the sleep flag mov d[_wdtcounter],0 mov w[_wdt],0 simpic4: call simpic1_wdt ; tmr0 is inactive so is fosc because it's a sleep instruction! cmp w[_wdt],18000 ; has wdt timed out 18 ms with no prescaler? jz simpic1_wdtout ; if so do reset in sleep mode test w[_config],010 ; looking for mclre jz simpic5 ; if tied to Vdd go onto simpic5 and check pin change call simpic_getgpio ; else check for mclr pin cmp al,04 ; pressed '3' jnz simpic5b ; carry on and check other two simpic5: ; if here we are checking the pin change shite call simpic_getgpio ; get the pins cmp al,04 ; pressed '3' jz simpic5a pop eax jmp breakmclr ; master clear reset ! simpic5b: cmp al,0b ; pressed '0' jz simpic5a cmp al,02 ; pressed '1' jz simpic5a jmp simpic4 ; repeat sleep instruction until time out simpic5a: ; reset the bugger due to pinchange during sleep and b[_status],07 ; 0000 0uuu or b[_status],090 ; 1001 0uuu call pic_por1 ; soft reset pop eax jmp breakwupc ;--------------------------------------------- simpic_getgpio: ; get the pins, use keyboard for now xor al,al ; clear it so that nothing is triggered by accident mov cl,b[turbo] ; get system flags test cl,010 ; no I/O ? (part of fast mode) jz ret ; ret out and do nowt test cl,8 ; if I/O enabled then is it keyboard or lpt ? jz simpic_getgpiolpt ; get it from lpt else get it from keboard in al,060 ; keys 0,1,3 for gp0,gp1,gp3/mclr ret simpic_getgpiolpt: ;we need to read the ports ret simpic1_wdtout: ; if here the wdt timed out while in sleep. and b[_status],07 ; gpwuf=0 to=0 pd=0 pop eax ; 32 bit addx twat call pic_por1 jmp breakwdt ; and break out simpic1_fosc: ; update the fosc oscilator inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well ret simpic1_t0cs: ; update the timer0 or counter (with pre-scaler if applicable) mov al,b[_option] ; get option byte test al,020 ; TOCS Timer or counter mode ? jz simpic1_t0cs_1 ; if zero then its TIMER MODE (inc every instruction cycle)...with no prescaler ;here we look at printer ports to see if external counter is high/low etc. ;because we have not developed this we simply ret with nothing done ret ; if true then its COUNTER MODE (inc every high/low on tocki pin) ;here we do timer mode simpic1_t0cs_1: ; If here its TIMER MODE inc every intruction cycle or fosc x 4 unless prescaler is active test al,08 ; PSA ? Timer or WDT jz simpic1_t0cs_2 inc b[_tmr0] ; if here it is assigned to the WDT and not timer0 ret ; so timer is updated every instruction cycle simpic1_t0cs_2: ;if here prescaler is assigned to timer0 and al,7 ; top bits of prescaler value mov cl,al mov al,080 ; 128 = 1/2, 64 = 1/4, 1 = 1/256 shr al,cl clc add b[_prescaler],al adc b[_tmr0],0 ret ;please check config to see if wdt is enabled !!!!!!!! simpic1_wdt: ; update the wdt (with pre-scaler if applicable) test b[_config],4 jnz simpic1_wdt_0 mov d[_wdtcounter],0 ; wdt is not counting so reset ret ; the wdt never times out EVER !!!! simpic1_wdt_0: ; if here wdte is active mov al,b[_option] ; get option byte test al,08 ; PSA ? Timer or WDT jnz simpic1_wdt_1 mov eax,d[_wdtcounter] mov w[_wdt],ax ; update the watch dog timer = 0 to 18000 us = 0.0 to 18.000 ms ret simpic1_wdt_1: ; if here prescaler is assigned to the wdt and al,7 ; top bits of prescaler value mov cl,al mov eax,d[_wdtcounter] shr eax,cl ; mov w[_wdt],ax ret dat: db 0 ; 00 = Do nothing ; 01 = Send out data to GPIO ; 03 = Read in data from GPIO ; xx = Undefined ! ; will hold the bit pattern for GPIO ports put_ports: ret get_ports: ret ;mov dx,w[prntrprt] ; 378 write data pin ;out dx,al ;jmp ret ;pic instructions start here !!!! ;- pic_nop: ; Nothing affected clc ret ;- pic_option: mov al,b[_w] ; get w mov b[_option],al ; store it clc ret ;- pic_sleep: or b[_flags],1 ; this effects the contents of the GPWUF bit mov w[_wdt],0 ; reset the watch dog timer (not a physical register) mov d[_wdtcounter],0 ; reset the watch dog timer (not a physical register) mov al,b[_status] or al,010 ; set TO bit and al,0f7 ; clear PD bit mov b[_status],al clc ret ;- pic_clrwdt: mov d[_wdtcounter],0 ; reset the watch dog timer (not a physical register) mov w[_wdt],0 or b[_status],018 ; set TO & PD bit clc ret ;- pic_clrw: mov b[_w],0 ; Clear w or b[_status],04 ; set the ZERO flag clc ret ;- pic_tris: and al,07 ; get the tris number cmp al,6 ; tris 6 is only valid jnz pic_tris_bad ; ***************** MICROCHIP TECHNICAL.... is this a NOP or does it crash ? mov al,b[_w] ; get the w register mov b[_tris],al ; store it into the tris register, only if it is it 6 clc ret pic_tris_bad: ; not sure what happens here clc ret ;- pic_movwf: call getaddx ; compute the address mov al,b[_w] ; get the w register mov b[bx+_indf],al ; stick in the memory stc ret ;- pic_clrf: call getaddx ; compute the address xor al,al ; clear or b[_status],04 ; set the ZERO flag mov b[bx+_indf],al ; stick in the memory stc ret ;- pic_subwf: mov ch,al ; save the direction bit for later shl ch,2 ; move the bit to the far left and ch,080 call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_w] ; get the w reg sub al,cl ; al now holds the answer lahf ; ah holds flags xor ah,01 rcr ah,1 rcr ch,1 ; transfer the carry bit rcr ah,4 rcr ch,1 ; transfer the DC or aux bit rcr ah,2 rcr ch,1 ; transfer the carry bit shr ch,4 ; mask out the three bits clc ; we dont want this brought in rcr ch,1 ; get thge direction flag jc pic_subwf1 ; is it 1 ? and b[_status],0f8 ; clear the z,dc,c flag or b[_status],ch ; update status mov b[_w],al ; store the answer clc ret pic_subwf1: and b[_status],0f8 ; clear the z,dc,c flag or b[_status],ch ; update status mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_decf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory dec al ; decrement, al now holds the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_decf1 ; is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; if not store in the w register mov b[_w],al ; store the answer clc ret pic_decf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; else store it in the file register mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_iorwf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_w] ; get the w reg or al,cl ; logical or, al now holds the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_iorwf1 ; is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[_w],al ; store the answer clc ret pic_iorwf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; else store it in the file register mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_andwf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_w] ; get the w reg and al,cl ; logical and, al now holds the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_andwf1 ; is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[_w],al ; store the answer in w clc ret pic_andwf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_xorwf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_w] ; get the w reg xor al,cl ;logical or, al now holds the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_xorwf1 ;is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[_w],al ; store the answer in acc clc ret pic_xorwf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[bx+_indf],al ; store the answer in the file register stc ret ;- pic_addwf: mov ch,al ; save the direction bit for later shl ch,2 ; move the bit to the far left and ch,080 call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_w] ; get the w reg add al,cl ; add them together, al now holds the answer lahf ; ah holds flags rcr ah,1 rcr ch,1 ; transfer the carry bit rcr ah,4 rcr ch,1 ; transfer the DC or aux bit rcr ah,2 rcr ch,1 ; transfer the carry bit shr ch,4 ; mask out the three bits clc ; we dont want this brought in rcr ch,1 ; get thge direction flag jc pic_addwf1 ; is it 1 ? and b[_status],0f8 ; clear the z,dc,c flag or b[_status],ch ; update staus mov b[_w],al ; store the answer in acc clc ret pic_addwf1: and b[_status],0f8 ; clear the z,dc,c flag or b[_status],ch ; update status mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_movf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory or al,al ; set flags lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_movf1 ; is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[_w],al ; store the answer into the acc clc ret pic_movf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; update staus ;mov b[bx+_indf],al ; store the answer back into the file register stc ret ;- pic_comf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory not al ; logical not, al now holds the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_comf1 ; is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[_w],al ; store the answer in w clc ret pic_comf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[bx+_indf],al ; store the answer in the file register stc ret ;- pic_incf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory inc al ; increment, al now holds the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and get the d bit jc pic_incf1 ; is it 1 ? and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status mov b[_w],al ; store the answer in w clc ret pic_incf1: and b[_status],0fb ; clear the zero flag or b[_status],ch ; update the status mov b[bx+_indf],al ; store the answer in the file register stc ret ;- pic_decfsz: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory dec al ; decrement, al now holds the answer rcl ch,3 ; get the d bit jc pic_decfsz1 ; is it 1 ? mov b[_w],al ; store the answer in acc jmp pic_decfsz2 pic_decfsz1: mov b[bx+_indf],al ; store the answer in the file register or al,al ; is the answer zero ? stc jnz ret ; if not the ret back and don't skip instruction inc w[_ip] ; else skip the next instruction inc d[_fosc] ; fosc + 1 inc d[_wdtcounter] ; do the wdt as well stc ret pic_decfsz2: or al,al ; is the answer zero ? clc jnz ret ; if not the ret back and don't skip instruction inc w[_ip] ; else skip the next instruction inc d[_fosc] ; fosc + 1 inc d[_wdtcounter] ; do the wdt as well clc ret ;- pic_rrf: mov ch,al ; save the direction bit for later rol ch,2 and ch,080 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_status] ; we need the carry bit rcr cl,1 ; get the carry rcr al,1 ; rotate right rcl ch,1 ; transfer the carry flag and get the d bit jc pic_rrf1 ; is it 1 ? and b[_status],0fe ; clear the carry flag or b[_status],ch ; update status mov b[_w],al ; store the answer clc ret pic_rrf1: and b[_status],0fe ; clear the zero flag or b[_status],ch ; else store it in the file register mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_rlf: mov ch,al ; save the direction bit for later rol ch,2 and ch,080 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory mov cl,b[_status] ; we need the carry bit rcr cl,1 ; get the carry rcl al,1 ; rotate right rcl ch,1 ; transfer the carry flag and get the d bit jc pic_rlf1 ; is it 1 ? and b[_status],0fe ; clear the carry flag or b[_status],ch ; update status mov b[_w],al ; store the answer clc ret pic_rlf1: and b[_status],0fe ; clear the zero flag or b[_status],ch ; else store it in the file register mov b[bx+_indf],al ; store the answer in the gile register stc ret ;- pic_swapf: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory ror al,4 ; swap the nibbles over rcl ch,3 ; get the d bit jc pic_swapf1 ; is it 1 ? mov b[_w],al ; store the answer in w clc ret pic_swapf1: mov b[bx+_indf],al ; store the answer in the file register stc ret ;- pic_incfsz: mov ch,al ; save the direction bit for later and ch,020 ; mask the direction bit call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory inc al ; increment, al now holds the answer rcl ch,3 ; get the d bit jc pic_incfsz1 ; is it 1 ? mov b[_w],al ; store the answer in acc jmp pic_incfsz2 pic_incfsz1: mov b[bx+_indf],al ; store the answer in the file register or al,al ; is the answer zero ? stc jnz ret ; if not the ret back and don't skip instruction inc w[_ip] ; else skip the next instruction inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well stc ret pic_incfsz2: or al,al ; is the answer zero ? clc jnz ret ; if not the ret back and don't skip instruction inc w[_ip] ; else skip the next instruction inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well clc ret ;- pic_bcf: mov cl,al ; get the bit value shr cl,5 ; cl=bit number 0 to 7 mov ch,1 ; start with bit 0 set call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory rol ch,cl ; position the bit not ch ; invert and al,ch ; clear the bit in al mov b[bx+_indf],al ; store it stc ret ;- pic_bsf: mov cl,al ; get the bit value shr cl,5 ; cl=bit number 0 to 7 mov ch,1 ; start with bit 0 set call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory rol ch,cl ; position the bit or al,ch ; set the bit in al mov b[bx+_indf],al ; store it stc ret ;- pic_btfsc: mov cl,al ; get the bit value shr cl,5 ; cl=bit number 0 to 7 inc cl ; if it is bit zero we need to rcr,1 to put it in the flags call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory rcr al,cl jc pic_btfsc1 ; just ret if it is not clear inc w[_ip] ; else skip the next intruction inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well pic_btfsc1: clc ret ;- pic_btfss: mov cl,al ; get the bit value shr cl,5 ; cl=bit number 0 to 7 inc cl ; if it is bit zero we need to rcr,1 to put it in the flags call getaddx ; compute the address mov al,b[bx+_indf] ; get the contents of the memory rcr al,cl jnc ret ; just ret if it is not set inc w[_ip] ; else skip the next intruction inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well clc ret ;- pic_retlw: mov b[_w],al ; put litteral into w register mov ax,w[_sp+1] ; pop the stack dec b[_sp] ; decrement the stack pointer. values>2 show stack overflow mov bx,w[_sp+3] ; get current stack contents mov w[_sp+1],bx ; move the stack inwards dec ax ; after this the ip is incremented 1 so dec it mov w[_ip],ax ; load the new address inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well clc ret ;- pic_call: mov bx,w[_sp+1] ; get current stack contents mov w[_sp+3],bx ; move the stack outwards mov bx,w[_ip] ; get the ip inc bx ; inc it and bx,03ff mov w[_sp+1],bx ; push the stack inc b[_sp] ; increment the stack pointer. values>2 show stack overflow xor ah,ah ; this leaves ax=8 bit address mov ch,b[_status] ; get the page select bit shr ch,4 and cx,0200 add ax,cx dec ax ; after this the ip is incremented 1 so dec it and ax,03ff mov w[_ip],ax ; load the new address inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well clc ret ;- pic_movlw: mov b[_w],al ; store the answer clc ret ;- pic_iorlw: xor ch,ch or b[_w],al ; store the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status clc ret ;- pic_andlw: xor ch,ch and b[_w],al ; store the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and b[_status],0fb ; clear the zero flag or b[_status],ch ; update status clc ret ;- pic_xorlw: xor ch,ch xor b[_w],al ; store the answer lahf ; ah holds flags rcl ah,2 ; put z flag into carry rcr ch,6 ; transfer the zero flag and b[_status],0fb ; clear the zero flag or b[_status],ch ; update the status clc ret pic_goto: and ax,01ff ; 0 to 511 mov ch,b[_status] shr ch,4 and cx,0200 add ax,cx dec ax ; after this the ip is incremented 1 so dec it mov w[_ip],ax inc d[_fosc] inc d[_wdtcounter] ; do the wdt as well clc ret pic_error: pop ax push ax ; we need to trap here when multi stepping clc ret ; this is to trap undefined routines above ;----------------------------------------------------------------------- ;computes the address using page bit and offset getaddx: and al,01f movzx bx,al ;word it ret ;ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ shrinkit_getfuse: ;fuse data is stored in different areas of each pic mov ax,w[pic_mem+01ffe] ;01ffe = 0fff = -1 which is where the fuses are ! ret ;called by header. ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;decode opcode and create text string output ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ; on entry w[_ip] = current ip value ; on exit cs:080 = string for address : bpx : cursor : mnemonic ; [picrout] = vector to simpic routine ; bx = opcode pic_rout: dw 0 ; this points to the correct simulation routine. mcx86: db 1 decodepic: ; decode and create string mov edi,080 ; point to dta mov ecx,60 ; 120 bytes to be cleared mov ax,02020 rep stosw ; clear the line mov edi,080 ; it all goes here mov ax,w[_ip] ; get the address call convert_16k stosd ; store address mov ax,02020 stosw ; store double space ready for mnemonic movzx esi,w[_ip] ; get the address sal esi,1 ; word align mov ax,w[esi+pic_mem] ; get opcode mov w[_oppcode],ax ; update the oppcode sal esi,1 ; dword align mov bl,b[esi+BPXMEM] ; get the BPX flag and bl,1 ; is there a BPX at this ip address ? jz decodepic0 ; if not then skip this lot else. mov bx,w[_ip] ; this ip address has a breakpoint set on it ! mov w[_brk],bx ; change brk so that it gets trapped mov b[edi-1],"" ; put marker in text (4 hours tracing this little bug *************) decodepic0: ; now do the mnemonics call fastdecode0 ; esi = vector, bx = opcode cmp b[mcx86],1 ; jz long decodepic0a ; microchip does the same as decode but puts different text into 080 call [esi*4+x86_vect] ; jump to relevent routine for X86 style mnemonics ret decodepic0a: call [esi*4+mcp_vect] ; jump to relevent routine for MCP style mnemonics ret x86_vect: ; vectors for x86 mnemonics dd decodepic1 ; pic_nop dd decodepic1 ; pic_option dd decodepic1 ; pic_sleep dd decodepic1 ; pic_clrwdt dd decodepic1 ; pic_clrw dd decodepic2 ; pic_tris dd decodepic31 ; pic_movwf dd decodepic3 ; pic_clrf dd decodepic41 ; pic_subwf dd decodepic4 ; pic_decf dd decodepic8 ; pic_iorwf dd decodepic8 ; pic_andwf dd decodepic8 ; pic_xorwf dd decodepic8 ; pic_addwf dd decodepic81 ; pic_movf dd decodepic4 ; pic_comf dd decodepic4 ; pic_incf dd decodepic4 ; pic_decfsz dd decodepic4 ; pic_rrf dd decodepic4 ; pic_rlf dd decodepic4 ; pic_swapf dd decodepic4 ; pic_incfsz dd decodepic6 ; pic_bcf dd decodepic6 ; pic_bsf dd decodepic6 ; pic_btfsc dd decodepic6 ; pic_btfss dd decodepic5 ; pic_retlw dd decodepic5 ; pic_call dd decodepic5 ; pic_movlw dd decodepic5 ; pic_iorlw dd decodepic5 ; pic_andlw dd decodepic5 ; pic_xorlw dd decodepic7 ; pic_goto dd decodepic1 ; pic_error ;???? ???? ???? Error (bad decode) possible data mcp_vect: dd decodemcp1 ; pic_nop dd decodemcp1 ; pic_option dd decodemcp1 ; pic_sleep dd decodemcp1 ; pic_clrwdt dd decodemcp1 ; pic_clrw dd decodemcp2 ; pic_tris dd decodemcp3 ; pic_movwf dd decodemcp3 ; pic_clrf dd decodemcp4 ; pic_subwf dd decodemcp4 ; pic_decf dd decodemcp4 ; pic_iorwf dd decodemcp4 ; pic_andwf dd decodemcp4 ; pic_xorwf dd decodemcp4 ; pic_addwf dd decodemcp4 ; pic_movf dd decodemcp4 ; pic_comf dd decodemcp4 ; pic_incf dd decodemcp4 ; pic_decfsz dd decodemcp4 ; pic_rrf dd decodemcp4 ; pic_rlf dd decodemcp4 ; pic_swapf dd decodemcp4 ; pic_incfsz dd decodemcp6 ; pic_bcf dd decodemcp6 ; pic_bsf dd decodemcp6 ; pic_btfsc dd decodemcp6 ; pic_btfss dd decodemcp5 ; pic_retlw dd decodemcp5 ; pic_call dd decodemcp5 ; pic_movlw dd decodemcp5 ; pic_iorlw dd decodemcp5 ; pic_andlw dd decodemcp5 ; pic_xorlw dd decodemcp7 ; pic_goto dd decodemcp1 ; pic_error ;???? ???? ???? Error (bad decode) possible data ;------------------------------------ no opperands decodepic1: ;no opperands call decodepic_xfr ;xfer first mnemonic string upto the colon. call decodepic_help ;end line with (comments if required) ret ;------------------------------------ imm3 decodepic2: ;fff x3 call decodepic_xfr ;xfer mov ax,bx ;restore oppcode call convert_3f ; mov ah,al mov al,"(" stosw mov al,")" stosb call decodepic_help ;end line ret ;------------------------------------- [mem] decodepic3: ;fffff x5 call decodepic_xfr ;xfer call decodepic3_mem5 call decodepic_help ;end line ret ;------------------------------------- decodepic3_mem5: mov ax,bx ;restore oppcode call convert_5f cmp al,030 ;leading zero ? jz decodepic3a mov b[di],030 ;if not put one in inc di decodepic3a: stosw mov b[di],"]" inc di ret ;-------------------------------------- [mem],w decodepic31: ;fffff x5 call decodepic_xfr ;xfer call decodepic3_mem5 mov ax,"w," stosw call decodepic_help ;end line ret ;------------------------------------ [mem] [mem](w) decodepic4: ;dfffff x1 + x5 call decodepic_xfr ;xfer call decodepic3_mem5 mov ax,bx rcr ax,6 ;put d flag into carry jc decodepic4a mov eax,")w( " ;************** [mem](w) stosd decodepic4a: call decodepic_help ;end line ret ;------------------------------------ [mem],w [mem],(w) decodepic41: ;dfffff x1 + x5 call decodepic_xfr ;xfer call decodepic3_mem5 mov ax,bx rcr ax,6 jc decodepic41a mov eax,")w(," ;************** [mem],(w) stosd jmp decodepic41b decodepic41a: mov ax,"w," ;************** [mem],w stosw decodepic41b: call decodepic_help ;end line ret ;------------------------------------- imm8 decodepic5: ;kkkkkkkk x8 call decodepic_xfr ;xfer mov ax,bx ;restore oppcode call convert_8k cmp al,030 jz decodepic5a mov b[di],030 inc di decodepic5a: stosw call decodepic_help ;end line ret ;-------------------------------------- [mem],imm3 decodepic6: ;bbbfffff x3 + x5 call decodepic_xfr ;xfer call decodepic3_mem5 mov al,"," stosb mov ax,bx ;restore oppcode shr al,5 call convert_3f stosb call decodepic_help ;end line ret ;-------------------------------------------- imm9 decodepic7: ;kkkkkkkkk x9 call decodepic_xfr ;xfer mov al,bh ;restore oppcode and al,01 or al,030 cmp al,030 ;leading zero ? jz decodepic7a ;if so carry on mov b[di],030 inc di decodepic7a: stosb ;put 9th bit in mov ax,bx ;restore oppcode call convert_8k stosw ;put other 8 bits in call decodepic_help ;end line ret ;------------------------------------ [mem],w w,[mem] decodepic8: ;dfffff x1 + x5 mov ax,bx rcr al,6 jnc decodepic81a call decodepic_xfr mov al,"[" stosb call decodepic3_mem5 mov ax,"w," stosw call decodepic_help ret ;------------------------------------ [mem] w,[mem] decodepic81: ;dfffff x1 + x5 mov ax,bx rcr al,6 jnc long decodepic81a call decodepic_xfr mov al,"[" stosb call decodepic3_mem5 call decodepic_help ret decodepic81a: call decodepic_xfr ;xfer mov ax,",w" stosw mov al,"[" stosb call decodepic3_mem5 ;finnish off mem5 call decodepic_help ret ;--------------------------------------------------------------------------- decodepic_xfr: ;xfer first part of mnemonic mov w[pic_rout],si ;save the index pointer for simpic ror eax,010 ror ecx,010 mov cx,010 ;screen x pos tracker mov ax,si ;si holds number from 0 to 37 mov ah,al ;ah holds oppcode value mov esi,mnemonic ;point to table decodepic_xfr1: lodsb ;get string ident cmp al,ah ;is it this one ? jz decodepic_xfr3 ;if so skip decodepic_xfr2: lodsb cmp al,":" jnz decodepic_xfr2 jmp decodepic_xfr1 decodepic_xfr3: ;if here we have found the correct string lodsb cmp al,":" jz decodepic_xfr4 stosb dec cx or cx,cx jnz decodepic_xfr3 decodepic_xfr4: ror eax,010 ror ecx,010 ret ;-------------------------------------------------------------------------- decodepic_help: ;add comment line ;put comment line here ;mov ax,0a0d ;stosw ;cr/lf for disk output ret mnemonic: db 00,"nop:" ;nop db 01,"option:" ;option db 02,"sleep:" ;sleep db 03,"clrwdt:" ;clrwdt db 04,"clrw:" ;clr w db 05,"tris:" ;tris(imm3) db 06,"mov [:" ;mov [mem],w db 07,"clr [:" ;clr [mem] db 08,"sub [:" ;sub [mem],w sub [mem],(w) db 09,"dec [:" ;dec [mem] dec [mem] (w) db 0a,"or :" ;or [mem],w or w,[mem] db 0b,"and :" ;and [mem],w and w,[mem] db 0c,"xor :" ;xor [mem],w xor w,[mem] db 0d,"add :" ;add [mem],w add w,[mem] db 0e,"mov :" ;mov [mem] mov w,[mem] *test flags db 0f,"not [:" ;not [mem] not [mem] (w) db 010,"inc [:" ;inc [mem] inc [mem] (w) db 011,"decsz [:" ;decsz [mem] decsz [mem] (w) db 012,"rcr [:" ;rcr [mem] rcr [mem] (w) db 013,"rcl [:" ;rcl [mem] rcl [mem] (w) db 014,"xchg [:" ;xchg [mem] xchg [mem] (w) db 015,"incsz [:" ;incsz [mem] incsz [mem] (w) db 016,"bitclr [:" ;bitclr [mem],imm3 db 017,"bitset [:" ;bitset [mem],imm3 db 018,"testsc [:" ;testsc [mem5],imm3 db 019,"testss [:" ;testss [mem5],imm3 db 01a,"ret w,:" ;ret w,imm8 db 01b,"call :" ;call imm8 db 01c,"mov w,:" ;mov w,imm8 db 01d,"or w,:" ;or w,imm8 db 01e,"and w,:" ;and w,imm8 db 01f,"xor w,:" ;xor w,imm8 db 020,"jmp :" ;jmp imm9 db 021,"error:" ;error (not supported) ;------------------------------------ no opperands decodemcp1: ;no opperands call decodemcp_xfr ;xfer first mnemonic string upto the colon. call decodemcp_help ;end line with (comments if required) ret ;------------------------------------ imm3 decodemcp2: ;fff x3 call decodemcp_xfr ;xfer mov ax,bx ;restore oppcode call convert_3f ; mov ah,al mov al,"(" stosw mov al,")" stosb call decodemcp_help ;end line ret ;------------------------------------- [mem] decodemcp3: ; fffff x5 call decodemcp_xfr ; xfer call decodemcp3_mem5 ; do mem5 call decodemcp_help ; end line ret decodemcp3_mem5: mov ax,bx ;restore oppcode call convert_5f cmp al,030 ;leading zero ? jz decodemcp3a mov b[di],030 ;if not put one in inc di decodemcp3a: stosw ret ;------------------------------------ [mem],F [mem],W decodemcp4: ; dfffff x1 + x5 call decodemcp_xfr ;xfer call decodemcp3_mem5 mov ax,bx rcr ax,6 jc decodemcp4a mov eax,"W," ;************** [mem],(w) stosw jmp decodemcp4b decodemcp4a: mov ax,"F," ;************** [mem],w stosw decodemcp4b: call decodemcp_help ;end line ret ;------------------------------------- imm8 decodemcp5: ;kkkkkkkk x8 call decodemcp_xfr ;xfer mov ax,bx ;restore oppcode call convert_8k cmp al,030 jz decodemcp5a mov b[di],030 inc di decodemcp5a: stosw call decodemcp_help ;end line ret ;-------------------------------------- [mem],imm3 decodemcp6: ;bbbfffff x3 + x5 call decodemcp_xfr ;xfer call decodemcp3_mem5 mov al,"," stosb mov ax,bx ;restore oppcode shr al,5 call convert_3f stosb call decodemcp_help ;end line ret ;-------------------------------------------- imm9 decodemcp7: ;kkkkkkkkk x9 call decodemcp_xfr ;xfer mov al,bh ;restore oppcode and al,01 or al,030 cmp al,030 ;leading zero ? jz decodemcp7a ;if so carry on mov b[di],030 inc di decodemcp7a: stosb ;put 9th bit in mov ax,bx ;restore oppcode call convert_8k stosw ;put other 8 bits in call decodemcp_help ;end line ret ;-------------------------------------------------------------------------- decodemcp_help: ;add comment line ;put comment line here ;mov ax,0a0d ;stosw ;cr/lf for disk output ret ;--------------------------------------------------------------------------- decodemcp_xfr: ;xfer mnemonic mov w[pic_rout],si ;save the index pointer for simpic ror eax,010 ror ecx,010 mov cx,010 ;screen x pos tracker mov ax,si ;si holds number from 0 to 37 mov ah,al ;ah holds oppcode value mov esi,mnemonicmc ;point to table decodemcp_xfr1: lodsb ;get string ident cmp al,ah ;is it this one ? jz decodemcp_xfr3 ;if so skip decodemcp_xfr2: lodsb cmp al,":" jnz decodemcp_xfr2 jmp decodemcp_xfr1 decodemcp_xfr3: ;if here we have found the correct string lodsb cmp al,":" jz decodemcp_xfr4 stosb dec cx or cx,cx jnz decodemcp_xfr3 decodemcp_xfr4: ror eax,010 ror ecx,010 ret ;On entry ax holds 2 byte string for actual hex value ;if the codfile is loaded we check to see if a label exists at the specified ;address we replace the address with the text string else we simply store what ;is already in ax stosw_var: ;stosw or string, decimal type 0 (direct replacement) cmp b[codfile],1 ; is codfile loaded jnz stosw_stosw ; if not just stosw and exit push ax,ebx,esi ; save it incase no label exists in which case we just stosw mov ax,bx and bx,05f call getaddx ; get the address 0 - 0ff movzx esi,bx mov ebx,esi sal ebx,2 ; * 4 sal esi,5 ; * 32 add esi,ebx ;(32+4+2) = *36 van9 width add esi,van9+4 lodsb ; get the byte at this address (dh is not used anywhere and will be preserved] cmp al,"." ;no label ? jz stosw_var_nl mov bl,b[edi-1] ; have we just stored a leading zero ? cmp bl,030 ; well is it an ascii zero ? jnz stosw_var0 ; if not just carry on else dec edi ; we need to over write it stosw_var0: ror ax,8 mov al,020 ; set to a space test b[turbo],040 jz @skip1 ; if dump to disk mode on then don't put nasty 0fx colour codes in mov al,b[colour1+4] @skip1: stosb ror ax,8 stosw_var1: stosb ; xfer 1st char of label lodsb cmp al,"." ;finnished label ? jz stosw_var_done cmp al," " ;finnished a 12 digit label so no "." exist ? jz stosw_var_done jmp stosw_var1 ;repeat for ever stosw_var_done: ;label all done mov al,020 ; set to a space test b[turbo],040 jz @skip2 ; if dump to disk mode on then don't put nasty 0fx colour codes in mov al,b[colour1+3] ; default colour or al,0f0 ;make it special @skip2: stosb pop esi,ebx,ax ret stosw_var_nl: ;no label so pop 2 byte string and exit pop esi,ebx,ax stosw_stosw: stosw ret mnemonicmc: db 00, "nop:" ;* nop db 01, "option:" ;option db 02, "sleep:" ;sleep db 03, "clrwdt:" ;clrwdt db 04, "clrw:" ;clr w db 05, "tris:" ;tris(imm3) db 06, "movwf :" ;movwf mem db 07, "clrf :" ;clrf mem db 08, "subwf :" ;sub [mem],w sub [mem],(w) db 09, "decf :" ;dec [mem] dec [mem] (w) db 0a, "iorwf:" ;or [mem],w or w,[mem] db 0b, "andwf:" ;and [mem],w and w,[mem] db 0c, "xorwf:" ;xor [mem],w xor w,[mem] db 0d, "addwf :" ;add [mem],w add w,[mem] db 0e, "movf :" ;mov [mem] mov w,[mem] *test flags db 0f, "comf :" ;not [mem] not [mem] (w) db 010,"incf :" ;inc [mem] inc [mem] (w) db 011,"decfsz :" ;decsz [mem] decsz [mem] (w) db 012,"rrf :" ;rcr [mem] rcr [mem] (w) db 013,"rlf :" ;rcl [mem] rcl [mem] (w) db 014,"swapf :" ;xchg [mem] xchg [mem] (w) db 015,"incfsz :" ;incsz [mem] incsz [mem] (w) db 016,"bcf :" ;bitclr [mem],imm3 db 017,"bsf :" ;bitset [mem],imm3 db 018,"btfsc :" ;testsc [mem5],imm3 db 019,"btfss :" ;testss [mem5],imm3 db 01a,"retlw :" ;ret w,imm8 db 01b,"call :" ;call imm8 db 01c,"movlw :" ;mov w,imm8 db 01d,"iorlw :" ;or w,imm8 db 01e,"andlw :" ;and w,imm8 db 01f,"xorlw :" ;xor w,imm8 db 020,"goto :" ;* jmp imm9 db 021,"ERROR:" ;error (not supported) ;uses ebx,esi,ax ;on exit di = _ip ; esi = vector ; bx = oppcode fastdecode: ;on exit si = vector bx = oppcode movzx ebx,w[_ip] ;get the address ;mov di,bx sal ebx,1 ;word align mov ax,w[ebx+pic_mem] ;ax=oppcode sal ebx,1 mov bl,b[ebx+BPXMEM] and bl,1 ; is bit 0 set, ie is there a BPX at this ip address ? jz fastdecode0 ; if not then skip this lot else. mov bx,w[_ip] ;this ip address has a breakpoint set on it ! mov w[_brk],bx ;change brk so that it gets trapped fastdecode0: ;after bpx we must carry on with decode to get simpic address etc mov bx,ax ; save ax = 12 bit oppcode and opperand xor esi,esi ; clear vector cmp ax,0 ; 0000 0000 0000 NOP jz long ret inc si cmp ax,2 ; 0000 0000 0010 OPTION jz long ret inc si cmp ax,3 ; 0000 0000 0011 SLEEP jz long ret inc si cmp ax,4 ; 0000 0000 0100 CLRWDT jz long ret inc si cmp ax,040 ; 0000 0100 0000 CLRW jz long ret inc si and ax,0ff8 ; 0000 0000 0fff TRIS or ax,ax jz long ret inc si and ax,0fe0 cmp ax,020 ; 0000 001f ffff MOVWF jz long ret inc si cmp ax,060 ; 0000 011f ffff CLRF jz long ret inc si and ax,0fc0 cmp ax,080 ; 0000 10df ffff SUBWF jz long ret inc si cmp ax,0c0 ; 0000 11df ffff DECF jz long ret inc si cmp ax,0100 ; 0001 00df ffff IORWF jz long ret inc si cmp ax,0140 ; 0001 01df ffff ANDWF jz long ret inc si cmp ax,0180 ; 0001 10df ffff XORWF jz long ret inc si cmp ax,01c0 ; 0001 11df ffff ADDWF jz long ret inc si cmp ax,0200 ; 0010 00df ffff MOVF jz long ret inc si cmp ax,0240 ; 0010 01df ffff COMF jz long ret inc si cmp ax,0280 ; 0010 10df ffff INCF jz long ret inc si cmp ax,02c0 ; 0010 11df ffff DECFSZ jz long ret inc si cmp ax,0300 ; 0011 00df ffff RRF jz long ret inc si cmp ax,0340 ; 0011 01df ffff RLF jz long ret inc si cmp ax,0380 ; 0011 10df ffff SWAPF jz long ret inc si cmp ax,03c0 ; 0011 11df ffff INCFSZ jz long ret inc si and ax,0f00 cmp ax,0400 ; 0100 bbbf ffff BCF jz long ret inc si cmp ax,0500 ; 0101 bbbf ffff BSF jz long ret inc si cmp ax,0600 ; 0110 bbbf ffff BTFSC jz long ret inc si cmp ax,0700 ; 0111 bbbf ffff BTFSS jz long ret inc si cmp ax,0800 ; 1000 kkkk kkkk RETLW jz long ret inc si cmp ax,0900 ; 1001 kkkk kkkk CALL jz long ret inc si cmp ax,0c00 ; 1100 kkkk kkkk MOVLW jz long ret inc si cmp ax,0d00 ; 1101 kkkk kkkk IORLW jz long ret inc si cmp ax,0e00 ; 1110 kkkk kkkk ANDLW jz long ret inc si cmp ax,0f00 ; 1111 kkkk kkkk XORLW jz long ret inc si and ax,0e00 cmp ax,0a00 ; 101k kkkk kkkk GOTO jz long ret inc si ret ; pic_error ;???? ???? ???? Error (bad decode) possible data ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;PIC program command routines LOAD/READ/INCPICIP/BEGIN/END commands ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;---------------------------------------------------------------------------- ;to read pic ; ;1. read data command ; ;to write pic ; ;1. load data command ;2. begin prog command ;3. end prog command ; ;to reset pic ; ;1. set gp0,gp1 and MCLR low ;2. while keeping gp0,gp1 low take MCLR from 0v to 14v ; ; ; ; ; ; ; pic_ip: dw 0 ;pic program counter pic_read: dw 6,14,4 ;length of command string, length of pic bit stream, command bit stream pic_load: dw 6,14,2 ; pic_incip: dw 6,0,6 ; pic_begin: dw 6,0,8 ; pic_end: dw 6,0,0e ; w_buffer: dw 0405 ;how many words to write (1024 + cfg word + ID) next 4 locations is ID then the microcode, after 4096 we are back to the start r_buffer: dw 01001 ;how many words to read (2048 + cfg word) 1024 total mem prntrprt: dw 0378 ;io address tmr: dw 01 ;4 = 10us (roughly) ;---------------------------------------------------------------------------- writepic: call powerdown call wait_ltmr call powerup ;auto gp0/gp1 low with vdd & vpp set high call wait1ms_tmr call writedata ;carry set if error call powerdown jmp start readpic: push start ;when picpor rets it will goto start call clrram ;only clear RAM when doing an extra read getpic: ;when reading in a HEX file we need to read the pic first call message2 call powerdown ;giving us the oscall, then load in HEX file. call wait_ltmr call powerup ;auto gp0/gp1 low with vdd & vpp set high call wait1ms_tmr call wait1ms_tmr call wait1ms_tmr call readdata call powerdown jmp pic_por ;power on reset values for pic this will ret to start ;---------------------------------------------------------------------------- ;on entry the pic should have just been initialised...so first mem is the fuses.... readdata: mov cx,w[r_buffer] ;should wrap around mov w[pic_ip],0 readdata0: push cx mov edi,fuses ;point to fuses movzx edx,w[pic_ip] ;pic instruction pointer shl edx,1 ;2 bytes to each location add edi,edx ;es:di now point to correct mem location call read_word ;on exit bp holds 12 bit word mov ax,bp stosw ;store the word.... first time is storing the fuses... because the pic is allways reset before use this will hold true call inc_picip_cmd ;point pic to next mem location pop cx ;1024 left to do dec cx or cx,cx jnz readdata0 mov cx,4096 ;total memory sub cx,w[r_buffer] ;how many bytes we read readdata2: ;move pointer past the page boudary and bring it to the start mov ax,w[fuses] ;get fuse data mov w[_config],ax ;copy to simpic ret ;---------------------------------------------------------------------------- writedata: mov cx,w[w_buffer] ;1024 12bit words to write mov w[pic_ip],-1 writedata0: push cx mov edi,pic_mem ;point to just past the fuses movzx edx,w[pic_ip] ;pic instruction pointer shl edx,1 ;2 bytes to each location add edi,edx ;es:di now point to correct mem location mov cx,10 ;time out (if more than 10 programmin pulses are needed then chip is buggered) writedata1: push cx es mov bp,w[edi] ;get the data WORD call write_word ;on entry bp=data word call begin_prog_cmd call end_prog_cmd call read_word ;read back the data word just stored es mov ax,w[edi] and ax,0fff and bp,0fff cmp ax,bp jz carryon ;value ok ? ;es mov w[di+02000],bp ;if not save the data read back pop cx dec cx or cx,cx jnz writedata1 ;loop until over programming pulses gave exceeded the limit pop cx stc ret ;ERROR............... Chip will not program (buggered) carryon: pop cx ;if here mem was loaded ok. ;es mov w[di+02000],bp ; call inc_picip_cmd ;point pic to next mem location pop cx ;1024 left to do dec cx or cx,cx jnz writedata0 clc ;no error OK...... ret ;---------------------------------------------------------------------------- ;Reads in 1 words from current IP ;on exit bp holds data read_word: call read_data_cmd ;send the read data command to pic mov bp,0 ;clear the data word mov cx,w[pic_read+2] ;get number of bits of data (12 bits + two dumb + 1 start bit and 1 stop bit) total=16 call clkhigh call clklow ;cycle the start bit read_word1: call clkhigh ;data is now present on pic pin call clklow call dtaread rcr al,1 ;put data bit into carry flag rcr bp,1 ;xfer data bit into BP dec cx or cx,cx jnz read_word1 shr bp,2 ;make 14 upto 16 so LSB is now at bit 0 call clkhigh call clklow ;cycle the stop bit ret ;---------------------------------------------------------------------------- ;writes 1 word to current IP ;on entry bp=data word to be written write_word: call load_data_cmd ;send the LOAD DATA command to pic mov cx,w[pic_load+2] ;get number of bits of data (12 bits + two dumb + 1 start bit and 1 stop bit) total=16 call clkhigh call clklow ;cycle the start bit write_word1: rcr bp,1 ;bring in LSB of command word jc write_word2 ;set to 1 ? call dtalow jmp write_word3 write_word2: call dtahigh write_word3: call clkhigh call clklow ;latch data into pic dec cx or cx,cx jnz write_word1 call clkhigh call clklow ;cycle the stop bit ret ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;PIC command routines, sends the LOAD/READ/INCPICIP/BEGIN/END commands ;лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл ;---------------------------------------------------------------------------- load_data_cmd: mov cx,w[pic_load] ;6 command bits mov bl,b[pic_load+4] ;pic READ DATA command call sendcommand call wait1ms_tmr call wait1ms_tmr ret ;---------------------------------------------------------------------------- read_data_cmd: mov cx,w[pic_read] ;6 command bits mov bl,b[pic_read+4] ;pic READ DATA command call sendcommand call dtatri call wait1ms_tmr call wait1ms_tmr ret ;---------------------------------------------------------------------------- inc_picip_cmd: inc w[pic_ip] ;update address mov cx,w[pic_incip] ;6 command bits mov bl,b[pic_incip+4] ;pic READ DATA command call sendcommand ret ;---------------------------------------------------------------------------- begin_prog_cmd: mov cx,w[pic_begin] ;6 command bits mov bl,b[pic_begin+4] ;pic READ DATA command call sendcommand call wait1ms_tmr call wait1ms_tmr ret ;---------------------------------------------------------------------------- end_prog_cmd: mov cx,w[pic_end] ;6 command bits mov bl,b[pic_end+4] ;pic READ DATA command call sendcommand call wait1ms_tmr call wait1ms_tmr ret ;----------------------------------------------------------------------------- ;on entry cx=number of bits to send ; bl=command string ;on exit CLK is always LOW sendcommand: call clkhigh rcr bl,1 ;bring in LSB of command word jc sendcommand1 ;set to 1 ? call dtalow jmp sendcommand2 sendcommand1: call dtahigh sendcommand2: call clklow ;latch data into pic dec cx or cx,cx jnz sendcommand ;repeat 6 times ret