Try our *UPDATED* boardview, bios, & schematic search. Over 2.3 million files for download!

Need software for Intelligent universal programmer lk48

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • stefankd
    Member
    • Jul 2026
    • 23
    • Bulgaria

    #221
    Originally posted by stj
    actually it would be simpler to rip the eprom apart in a disassembler and run it in an emu than try to decode a comms log.
    it's a *very* simple 8bit cpu with almost no pheripherals to create a memory map for.
    you could probably emulate it in MAME !
    https://github.com/mamedev/mame/
    you're probably right and so far even that simple comms log I cannot make any sense of it - it's consistent though - by that I mean every time I run AEC software that is the log I get after the software shows "Labtool-48 found" and "Firmware version: 2.20".

    however, I see nothing in that log that can resample anything "structured", I mean I was expecting to see something like "GET_FW_VER_COMMAND" send and then response with "2.20", but I see nothing like that to a point that I wonder if in QEMU source code:


    https://github.com/qemu/qemu/blob/master/hw/char/parallel.c

    all those pdebug()
    calls are on the right place and not that something there is a miss, i.e. small bug in QEMU logging. BTW, if someone else wants to make such logs and investigate here is something like a very short HOWTO guide:

    ======================================================================
    Ubuntu 22.04.2 LTS x64 : no any particular reason, just what I had in hand for years on one old hdd

    # wget https://download.qemu.org/qemu-6.2.0.tar.bz2 : again, getting QEMU v6.2 source code for no any particular reason other than that QEMU version was already installed in my Ubuntu 22.04.2 LTS
    , i.e. i wanted to replace just the executable with my modified one and not the whole QEMU installation

    # tar xjvf qemu-6.2.0.tar.bz2
    # cd qemu-6.2.0

    # vi hw/char/parallel.c : or any other text editor if 'vi' is too weird for you and modify the line I mentioned in my previous post to activate the debug logging


    # ./configure --target-list=x86_64-softmmu : depending on your environment it will fail several times complaining about missing dependencies, in my case I was missing "ninja" and "libpixman" and needed to install them:

    # apt install ninja-build
    # apt install libpixman-1-dev

    # ./configure --target-list=x86_64-softmmu :
    run it again for final configuration after all the missing dependencies in your environment are installed.

    # make -j8
    # mv qemu-system-x86_64 myqemu-system-x86_64 : rename the newly build modified QEMU and so it can exist with the original one installed in your system

    # modprobe parport_pc : load the driver for your LPT hardware with Linux support, in my case LPT
    port build-in the motherboard, hence the "parport_pc​" driver (kenrel module), but it could be any PCI/PCIe LPT card, etc as far as it has Linux drivers that create "parport" Linux device, then it will work

    then run the modified for LPT logging "myqemu-system-x86_64" QEMU with:

    # ./myqemu-system-x86_64 -enable-kvm -cpu host -m 256 \
    -drive format=raw,file=xpsp3.raw \
    -serial none -parallel /dev/parport0

    where "xpsp3.raw" image is your WinXP installation QEMU raw image and "/dev/parport0
    " is the device file of your motherboard real HW LPT port.

    so, it's pretty easy and fast - building QEMU is surprisingly fast - maybe 10 minutes time even on that 15 years old computer. of course, you need to have image with WinXP installation
    ​, which I am omitting to include in this short guide how to prepare, because it's documented already by many other guides how to install WinXP in QEMU and prepare such image.
    ======================================================================

    also, you can use the above procedure to run the programmer in the future, i.e. when there will be no way on that very modern future computer to install WinXP/Win7/Win10, etc and the AEC software cannot work in that HW/OS of the future (as far as you have PCIe LPT card with Linux driver that creates "parport" device). so, it's not a total waste to know the above, even if it's not about reverse-engineering of the communication.

    Comment

    • stj
      Great Sage 齊天大聖
      • Dec 2009
      • 31944
      • Albion

      #222
      well given the small 8bit cpu, comms are probably kept small and simple.
      the pc probably sends an "init" command,
      and the programmer probably responds with a numeric code for the model & firmware.
      probably with some checksum's on each data packet.

      Comment

      • stefankd
        Member
        • Jul 2026
        • 23
        • Bulgaria

        #223
        Originally posted by stj
        and the programmer probably responds with a numeric code for the model & firmware.
        my main point though is different and it is that there is no "pp: rd" on my log anywhere and yet the FW revision information is properly exchanged, which leaves only 2 possibilities (IMHO):

        1) there is bug in QEMU logging, i.e. what I wrote in my previous post as possibility about the "pdebug() calls" and that is why no such "pp: rd" is logged (BTW, that is now ruled out as you will read below)

        or

        2) if QEMU logs everything properly, since obviously there is no any read-backs of the Parallel Port "DATA"-register, what is left as option is that they encode "nibbles" (because there is no space for a whole byte there) from the response as part of the Parallel Port "CONTROL"-register and/or "STATUS"-register, which makes it insanely more complicated.

        so, thanks to my HOWTO guide from my previous post, a friend already made logs from FW3.10 and FW4.10 units - he doesn't allow me to post the whole logs as he fear his SN are encoded there as well, but here is very small and the relevant portion of those logs:

        Code:
        grep "pp: rd3" logfw310.txt


        Code:
        pp: rd34
        pp: rd38
        pp: rd33 //FW ver read 1
        pp: rd31 //FW ver read 1
        pp: rd30 //FW ver read 1
        pp: rd34
        pp: rd38
        pp: rd33 //FW ver read 2
        pp: rd31 //FW ver read 2
        pp: rd30 //FW ver read 2
        pp: rd34
        pp: rd38
        pp: rd33 //FW ver read 3
        pp: rd31 //FW ver read 3
        pp: rd30 //FW ver read 3
        pp: rd34
        pp: rd38
        pp: rd33 //FW ver read 4
        pp: rd31 //FW ver read 4
        pp: rd30 //FW ver read 4
        Code:
        grep "pp: rd3" logfw410.txt

        Code:
        pp: rd34
        pp: rd38
        pp: rd34 //FW ver read 1
        pp: rd31 //FW ver read 1
        pp: rd30 //FW ver read 1
        pp: rd34
        pp: rd38
        pp: rd34 //FW ver read 2
        pp: rd31 //FW ver read 2
        pp: rd30 //FW ver read 2
        pp: rd34
        pp: rd38
        pp: rd34 //FW ver read 3
        pp: rd31 //FW ver read 3
        pp: rd30 //FW ver read 3
        pp: rd34
        pp: rd38
        pp: rd34 //FW ver read 4
        pp: rd31 //FW ver read 4
        pp: rd30 //FW ver read 4
        ​​

        so, the above not only proves there is no bug in the QEMU logging, but it also makes perfect sense that they read the FW version 4 times on Initialization:

        3 times to test for EPP, ECP and Bi-Directional (as they call it) mode work-ability in the system and then one final read in the selected preferred mode (which preference is EPP->ECP->Bi-Directional
        based on which exact modes failed and which worked as they documented and I posted in my previous post).

        also, that means the only option left for FW2.20 is the option 2), i.e. they are doing nibble-encoding in the STATUS/CONTROL-register bits for read-back-channel rather than using the DATA-register. that also explains why they claim such performance boots with no real change in the hardware, according to their website:


        LabTool-48XP advantage over the LabTool-48
        Double the speed - benchmark

        LT-48 versus LT-48XP
        Blank Check 59 sec 19 sec
        Program 140 sec 58 sec
        Verify 62 sec 32 sec
        Total 261 sec 109 sec (2.4 time faster)​


        that is due to that more efficient communication protocol actually using the Parallel Port "DATA"-register for a read-back in FW3.x/4.x. bottom line is communication of FW2.x is insanely more complicated compared to FW3.x/FW4.x and at least I cannot decode it even with that nibble-encoding in the STATUS/CONTROL-register bits hypothesis (which is most like not a hypothesis, but the reality of what they are actually doing).

        [EDIT] actually, it seems
        some of those nibble-encoding mechanisms were documented in articles for example by Douglas Boling, PC Mag Oct 27, 1992 and PC Magazine issue, Vol 11, No. 18, etc and in very short:


        Encoding a read-back channel in a classic unidirectional parallel port (Standard Parallel Port / SPP) uses Nibble Mode (IEEE 1284 Mode 1), which multiplexes an 8-bit byte into two 4-bit nibbles sent sequentially over the 5-bit Status Register input lines​


        so, I think we can say FW2.x for sure uses SPP with some kind of nibble-mode and no wonder LT48 is 2 times slower on average, because you read-back each byte as 2x 4-bit nibbles.

        Comment

        • stj
          Great Sage 齊天大聖
          • Dec 2009
          • 31944
          • Albion

          #224
          pp: rd34
          pp: rd38
          pp: rd34 //FW ver read 1
          pp: rd31 //FW ver read 1
          pp: rd30 //FW ver read 1
          so the whole 5 bytes is "48410"
          so is the 48 the hardware id? maybe.

          btw, these programmers and most from other makers work by loading an algorythm into a ram-based FPGA and then handing control to it.
          the FPGA then sits between the parallel port and the pin-driver circuits and streams the data.

          i dont have a UXP to examin the board, but i wouldnt be surprised if either the 8031 or the cypress MCU is doing on-the-fly USB to Parallel conversion.
          thats the only logical reason for the USB mode to be slower than the parallel-port.

          Comment

          • stefankd
            Member
            • Jul 2026
            • 23
            • Bulgaria

            #225
            Originally posted by stj
            so the whole 5 bytes is "48410"
            so is the 48 the hardware id? maybe.
            yep, I totally agree with you! those 0x34, 0x31, 0x30 seems to be just ASCII for each digit of the FW version, i.e. ASCII
            0x34 = 4, ASCII ​ 0x31 = 1, ASCII ​ 0x30 = 0 and hence firmware "​4.10" and the other 2 bytes form "48", i.e. the ID of the programmer.

            Originally posted by stj
            btw, these programmers and most from other makers work by loading an algorythm into a ram-based FPGA and then handing control to it.
            the FPGA then sits between the parallel port and the pin-driver circuits and streams the data.
            indeed, the software is just a front-end, it selects and sends the "program" from those "*.rez" files for each particular IC and hence the actual bit-banging of the pins is done entirely in hardware and it's done in such way and so the actual programming algorithm cannot be reversed with spying the Parallel port communication. BTW, LT48 includes "ICTEST.exe" that actually allows bit-banging of the pins
            ​ from the host, i.e. from the PC software.

            however, now with getting good insides about how at least FW3.x/FW4.x talk to the device it's possible open-source/alternative front-end to be developed. I guess the number of commands is very small GET_DEV_ID, GET_FW_VER, SEND_BYTE, etc to upload the actual "program"​ with the programing algorithm to the hardware. also, that way no U62 commutation can be ensured and thus no bricks.

            now, if someone is capable enough to reverse-engineer the "*.rez" files
            ​ and hence the programming algorithms that will be amazing, because it will allow even adding new IC support. also, if FW3.x/4.x have bit-banging capabilities like FW2.x then even be possible to do the programing from the host PC software and not need to write any "*.rez"​ programs.

            Comment

            • stj
              Great Sage 齊天大聖
              • Dec 2009
              • 31944
              • Albion

              #226
              well, i would be interested in knowing what that"ATtiny" chip connects with, the 8031 and / or the FPGA

              Comment

              • coromonadalix
                Member
                • May 2013
                • 34
                • canada

                #227
                some basics was done there for the devices files in 2009

                https://hackmii.com/2009/02/48uxp_sw/


                parse.py link


                https://limewire.com/d/m8yyo#n7A94obSFZ

                Comment

                • coromonadalix
                  Member
                  • May 2013
                  • 34
                  • canada

                  #228
                  dang forgot to add GDBA___.txt wayback machine of 2009 has it, other years and snapshot is dead

                  https://limewire.com/d/i2aMZ#Gxg5tGWhhB

                  Comment

                  • stefankd
                    Member
                    • Jul 2026
                    • 23
                    • Bulgaria

                    #229
                    Originally posted by coromonadalix
                    some basics was done there for the devices files in 2009

                    [URL="https://hackmii.com/2009/02/48uxp_sw/"]https://hackmii.com/2009/02/48uxp_sw/

                    that's actually very complicated and since there is no way to analyze the XC3030A bitstreams and thus create our own such bitstreams ​it leaves really only one option - if there is XC3030A bitstreams​ and/or FW functions that allows:

                    1) pin bit-banging from the host
                    2) control the DACs output/the voltages of each pin

                    which will make possible new programming algorithms (for unsupported devices) to be implemented from the host, i.e. use the current software for what it already supports and above to allow adding new device support with the algorithm running on the host instead inside the XC3030A bitstreams​​

                    that means the key to such idea/possibility is still the "ICTEST.exe" for 48/48LV and the understanding why it is not available for 48xp/48uxp, i.e. they just abandoned it due to no customer demand for such feature, but still 48xp/48uxp​ FW has the necessary software infrastructure to support such feature or there is no way to make "ICTEST.exe"​ for 48xp/48uxp
                    ​, because they changed the FW to disable the ability to do 1-2).

                    in other words and in very short - making open-source "ICTEST.exe"​ for 48xp/48uxp
                    ​ (if possible) is the best next step to be explored. unfortunately, 1st the weird nibble-mode using SPP that 48/48LV ​is using for Parallel communication needs to be understood.

                    Comment

                    • stefankd
                      Member
                      • Jul 2026
                      • 23
                      • Bulgaria

                      #230
                      Originally posted by stefankd
                      unfortunately, 1st the weird nibble-mode using SPP that 48/48LV is using for Parallel communication needs to be understood.
                      made key progress on that, because i succeeded in patching "LTKP1.SYS" and the EXE to use "Jungo WinDriver v5.03" - why that is crucial first step - because AEC used WinDriver v5.05 to develop the LPT drivers, which is long gone. however, version 5.03 is still available and "archived" for example here:
                      http://old-dos.ru/index.php?page=fil...show&id=105703

                      the *.SYS and the EXE have 2 checks - very easy to find using 0x1F9 (505) as a clue - just change it to 503 (0x1F7) and that's it. so, while I did it with the 48/48LV *.SYS and EXE exactly the same approach should be applicable for the 48XP/UXP *.SYS and EXE.

                      now, having "downgraded" the WinDriver from 5.05 to 5.03 and having the whole WinDriver ​v5.03 SDK lays the ground work open-source LPT drivers to be developed. I see more challenging (harder) the part of initial skeleton (doing initially nothing) driver that the EXE accepts to be made than the rest of it, because the rest of it is doing WinDriver's ​WD_TRANSFER (to the LPT IO Port) via WinDriver's ​KP_DeviceIoControl() calls and that way implementing all the commands that are easily identifiable in the AEC *.SYS​, for example:

                      Code:
                      LT_CMD_3TTL_STR_TRANSFER
                      g_trs_Cmd_C_St_High
                      even the names AEC used are again very hard to "decrypt" for example I guess "g_trs_Cmd_C_St_High​" is actually "Global (as prefix for global variable) Transfer Command Control Status High" and again i am guessing that is the High as in High bits, etc. so, essentially for each such command AEC defined/initialized separate WinDriver's ​WD_TRANSFER​ structure.

                      Comment

                      • stj
                        Great Sage 齊天大聖
                        • Dec 2009
                        • 31944
                        • Albion

                        #231
                        you would need to put the original driver through ghidra or ida-pro or maybe binary-ninja

                        as for the previous posts about custom bitstreams, forget that until somebody draws a schematic.

                        Comment

                        • stefankd
                          Member
                          • Jul 2026
                          • 23
                          • Bulgaria

                          #232
                          Originally posted by stj
                          you would need to put the original driver through ghidra or ida-pro or maybe binary-ninja
                          of course, I've already done that - otherwise how I would have found how to patch the original AEC *.SYS and the EXE to work with WinDriver 5.03 (instead the original v5.05 used by AEC) and without such patch - nothing further is really possible (or possible, but involves a lot more work to write code to emulate the whole WinDriver environment instead just use it).

                          Originally posted by stj
                          as for the previous posts about custom bitstreams, forget that until somebody draws a schematic.
                          essentially, we don't need custom bitstreams as far as there is way to control the pin bit-banging and the voltages from the host like "ICTEST.exe" is doing for 48/48LV, which is still not clear if it's possible with 48xp/uxp. it's for sure possible with 48/48lv, because otherwise "ICTEST.exe" cannot work. so, I am still looking to understand how "ICTEST.exe" is doing it. there will be real proof-of-concept when open-source/alternative "ICTEST.exe" is made.

                          BTW, I don't want to jinx it with announcing anything prematurely, but I've almost (fully) reverse-engineered the client-side, i.e. be able to talk to their original WinDriver LPT *.SYS and send commands to the programmer using it. so, maybe, there is no even point (at least for the time being) to write open-source/custom alternative LPT *.SYS, just exploit the one they made. it's insane AEC WinDriver ​license is inside their EXE in plaintext - otherwise it's not possible to connect to the driver - that is the first thing exchained between the client EXE and the driver, i.e. valid licence information.

                          so, now if way for pin bit-banging and the voltages​ is found then putting the programming algorithm for a particular device in that open-source alternative client means programming from the host without any special bitstream. also, that same can be used as a base for open-source/alternative "ICTEST.exe"​.

                          anyway, it feels at the moment it's unraveling really fast, but that is all thanks to the QEMU logging (making the process almost brain-dead, because it's just compare if the AEC EXE and my alternative client EXE are doing the same LPT operations logged by QEMU) and the patch to use WinDriver 5.03​ instead 5.05 really helps even more, because that allows to compare via WinDriver ​debug information what operations is calling the original EXE and replicate them in that open-source alternative client ​EXE - for example things like that the license information was properly exchanged, etc. so, QEMU logging covers the "hardware conversation" and WinDriver ​debug​ covers the "WinDriver ​and its client conversation​", i.e. whoever is working on it is longer totally blind, which allows fast progress.

                          however, no matter that progress I still don't have enough even to get the FW Version information and so it's really in very early stage, but for me most important is that from here one, based on the information I've already shared about QEMU logging and WinDriver 5.03​ even if I don't have time or energy to finish it someone else is possible to take over, because really all of that information is the groundwork that allows real results be achieved and it's no longer just unverified ideas and hypothesis.

                          [EDIT] just to give visual idea about the progress with the screenshot below:

                          * in Red are the WinDriver
                          operations original AEC EXE is doing for "Get FW Version" - even not visible on the picture it's total of 72 lines.
                          * as you can see first 28 lines without 3 lines in Red, I already made identical in my alternative client EXE to the original AEC EXE​, i.e. (28/72)*100 = 38.8% we can say almost 40% of "Get FW Version"​ proof-of-concept alternative client EXE to the LPT *.SYS is done.
                          * pay special attention to the line "Table_add (lic): new handle 1" - that is the license exchange that I mentioned is the first thing that is done
                          * all those "KP_Call: entered" are actually WinDriver's ​WD_TRANSFER (to the LPT IO Port) via WinDriver's ​KP_DeviceIoControl() calls​, i.e. sending specific Command to the unit or reading the answer (and QEMU log comes in place to see what was the actual hardware talk over the LPT)

                          * now "line 11", "line 18" and "line 24" that are missing from my alternative EXE are currently the show-stopper, because they cause BSoD and I cannot understand/find the code that corresponds to them in the original AEC EXE to replicate



                          Click image for larger version  Name:	progress.png Views:	0 Size:	11.5 KB ID:	3917534

                          Comment

                          • stefankd
                            Member
                            • Jul 2026
                            • 23
                            • Bulgaria

                            #233
                            good news and bad news:

                            * the good news is that i managed to fix all WinDriver related structures and memory allocations, i.e. no longer BSoD and crashes. that lead to proper communication between my own EXE client and AEC *.SYS LPT drivers - I can send commands to the *.SYS and receive proper answer - the example below is the first Command send by AEC original EXE, "Get_Driver_Version" (its ID is 0x2f), but this time send by my own EXE and obviously the answer is correct (please, note that "LTKP1 Driver V1.58 for ADVANTECH EQUIPMENT CORP." is no where coded in my EXE, i.e. it is not hard-coded in my EXE - it comes as an answer from the AEC *.SYS LPT drivers) :



                            * the bad news from perspective A - next command send by AEC original EXE is with ID 0x1d it's doing the following (collected on QEMU log):

                            Code:
                            pp: wd4c
                            pp: rs80
                            pp: wcc1
                            pp: wcc0
                            in other words: Write 0x4c to LPT Data Register, Read LPT Status Register​, Write 0xc1 to LPT Control Register​​, Write 0xc0 to LPT Control Register​​


                            however, when i call that command ​0x1d from my EXE, the first operation "pp: wd4c​" is instead "pp: wde8​", i.e. it instead writes wrong value of 0xe8 for some reason I cannot figure out for hours. maybe it's again due to some memory corruption I still haven't fixed between my EXE and AEC *.SYS LPT drivers​ communication related to WinDriver (which initially prevented command 0x2f to work properly as well). so, after I cannot figure it out that way I tried the following:

                            * the bad news from perspective B​ - command 0x1d is sent in AEC *.SYS LPT drivers​ disassembler-ed code in the following way:

                            Code:
                              _KP_DeviceIoControl(IOCTL_WD_MULTI_TRANSFER, param01, &g_trs_L_Cmd_HL, 0x60);
                            the size is 0x60 or 96, because WinDriver's WD_TRANSFER structure is 24 bytes in size and obviously for "multi-transfer" of 4 bytes that is 4*24=96 bytes. so, everything seems OK. however, when I wrote the following simple WinDriver code:


                            Code:
                            WD_TRANSFER Trans[4];
                            
                            BZERO(Trans);
                            
                            Trans[0].cmdTrans = WP_BYTE;
                            Trans[0].dwPort = 0x378;
                            Trans[0].Data.Byte = 0x4c; //pp: wd4c
                             //Trans[0].fAutoinc = FALSE;
                             //Trans[0].dwOptions = 0;
                            
                            Trans[1].cmdTrans = RP_BYTE;
                            Trans[1].dwPort = 0x379; //pp: rs80
                            
                            Trans[2].cmdTrans = WP_BYTE;
                            Trans[2].dwPort = 0x37a; //pp: wcc1
                            Trans[2].Data.Byte = 0xc1;
                            
                            Trans[3].cmdTrans = WP_BYTE;
                            Trans[3].dwPort = 0x37a; //pp: wcc0
                            Trans[3].Data.Byte = 0xc0;
                            
                            WD_MultiTransfer(hWD, &Trans, 4);​
                            the above code doesn't work skipping (at random AFAICT) one of the byte-writes, i.e. it writes 2 instead of 3 bytes. now, that's the shocker and why I am totally stuck, because the above code has nothing to do with AEC, but it's generic WinDriver code.

                            so, I doubt there are any WinDriver experts to suggest any explanation what is wrong with the above generic code, but now the main open questions is: How to implement "multi-transfer"
                            ​ with WinDriver ​that actually works?! it's Friday evening and I am pretty tired, but I see nothing (obviously) wrong in the above very simple and basic code - I mean it cannot be more simple... yet it doesn't work...

                            Comment

                            • stefankd
                              Member
                              • Jul 2026
                              • 23
                              • Bulgaria

                              #234
                              Originally posted by stefankd

                              * the bad news from perspective A
                              fixed that problem and it's not related to:

                              Originally posted by stefankd
                              * the bad news from perspective B
                              and so I still cannot do proper WinDriver's "multi-transfer" as described in "perspective B
                              ", but that is irrelevant for the time-being - that will be important when work on replacing the original AEC *.SYS, but currently my replacement EXE is finally able to "call" the original AEC *.SYS​ and instruct it to do the WinDriver's "multi-transfer"​.

                              so, the problem from "from perspective A​" of course was memory corruption - I still don't fully understand it, but it has to do with memory alignment or something - when I pass buffer to serve as a "mailbox" between the EXE and the *.SYS​ communication, if it's under certain size some parts of it gets overwritten, i.e. corrupted. I am very glad I hit that problem, because fixing it improved tremendously how I was doing "Get_Driver_Version" (CMD_ID: 0x2f)​. now it's 100% same as in the original AEC EXE based on the memory dumps I examined.

                              that means now I have properly working both type of commands:

                              * CMD_ID 0x2f​ ("Get_Driver_Version"​) that is just talk between the EXE and the *.SYS​, but no hardware talk to the LPT and
                              * CMD_ID 0x1d ("g_trs_L_Cmd_HL​" - whatever that is supposed to mean - Global_Transfer_L_Command_High/Low, but what "L" stands for, I mean what it abbreviates?? - I have no idea at the moment), which is talk between the EXE and the *.SYS
                              ​ plus talk to the hardware.

                              so, from here on I don't expect major problems - it's just insane amount of mostly routine work, because just to "GET_FW_VER" insane amount of such commands need to be implemented, but it should be more or less routine work, because it's the same as how I implemented "CMD_ID 0x1d​" just different values. All the Nibble-mode encoding parsing is done in the AEC *.SYS​ and so that leaves most of the complexity there and not in the Client EXE.

                              one more time - I am not sure if I will even finish it, but those post I made here are mostly for the next guy (if there ever will be such guy) to be able to follow and don't start totally from scratch.

                              Comment

                              • stj
                                Great Sage 齊天大聖
                                • Dec 2009
                                • 31944
                                • Albion

                                #235
                                i cant help thinking this is just more mess.
                                if you know what the aec software commands are trying to do, why not write a fake driver from scratch that just hits the hardware at 378?
                                if that works then maybe expand it fo forward into say a WCH USB2COM driver - or just hit the chip directly using LibUSB
                                https://libusb.info/

                                Comment

                                • stefankd
                                  Member
                                  • Jul 2026
                                  • 23
                                  • Bulgaria

                                  #236
                                  Originally posted by stj
                                  i cant help thinking this is just more mess.
                                  I am not sure I understand what you mean, because my goal is to port the DOS tool "ICTEST.exe" (available only for 48/48LV) to Windows in order to have Bit-banging capabilities from the host and thus be able to implement custom programing algorithms for unsupported devices. also, if you follow the analysis here:

                                  https://hackmii.com/2009/02/48uxp_sw/

                                  and compare 48/48LV and 48XP/UXP Bit-streams for the same chips - they are the same, i.e. basically that means the schematic of the Top-Board inside of those programmers is the same.

                                  now, if the "ICTEST.exe" is doing the Bit-banding and the DAC voltage control via some "generic" Bit-stream (and not via FW commands that they removed in 48XP/UXP
                                  firmwares), which Bit-stream allows such controls from the host, then it means that particular Bit-stream inside "ICTEST.exe" is the holly-grail even for 48XP/UXP, because it will allow custom programming algorithms to be implemented. currently, my progress is as follows:

                                  Click image for larger version  Name:	aec_hack_260823.png Views:	0 Size:	9.1 KB ID:	3923600


                                  or in other words, I finally progressed enough to get the DEV_ID and FW_VER of the programmer (please, note that exclamation mark "!" in front of "Labtool-48" is exactly how the programmer returns its ID, i.e. it's not added by me). also, I can now get the "Usage Statistics", i.e. how many chips that programmer has programmed via its life-time. BTW, maybe someone thinks that is like few lines of code and about what "finally progressed enough to get the DEV_ID and FW_VER​" I am talking about - unfortunately that is almost 1000 lines of code, because it requires over 900 LPT operations - that is due to from one side the very inefficient SPP mode with Nibble-encoding that is used with 48/28LV plus the overhead​ for dealing with Jungo WinDriver. so, it was substantial effort from my side and took all my free time in the last couple of weeks, because writing the code is actually on top of first reverse-engineer the communication protocol.

                                  Originally posted by stj

                                  if you know what the aec software commands are trying to do, why not write a fake driver from scratch that just hits the hardware at 378?
                                  actually, that was one of the 1st things I did as part of my reverse-engineering effort:

                                  Click image for larger version  Name:	my_sys.png Views:	0 Size:	20.6 KB ID:	3923601


                                  instead of the original AEC Driver, which ID-entifies as:

                                  Click image for larger version  Name:	aec_sys.png Views:	0 Size:	21.3 KB ID:	3923602

                                  Comment

                                  • stj
                                    Great Sage 齊天大聖
                                    • Dec 2009
                                    • 31944
                                    • Albion

                                    #237
                                    nice work
                                    i can imagine all the crap required to bitbang through a driver layer.
                                    setting direction registers and then setting and clearing bits over and over again.
                                    reminds me of the old days with 6502 code!

                                    Comment

                                    • stefankd
                                      Member
                                      • Jul 2026
                                      • 23
                                      • Bulgaria

                                      #238
                                      Originally posted by stj
                                      nice work
                                      i can imagine all the crap required to bitbang through a driver layer.
                                      setting direction registers and then setting and clearing bits over and over again.
                                      it's just what they did is very inefficient - come on - almost 1000 lines of code in C just to get the DEV_ID and FW_VER. even more the SPP with Nibble encoding is just small portion of the overhead, in fact the smallest one. IMHO, the biggest overhead comes from the use of Jungo WinDriver and the way how they implemented that additional layer. it also adds another problem, as I already mentioned:

                                      Originally posted by stefankd
                                      it's insane AEC WinDriver license is inside their EXE in plaintext - otherwise it's not possible to connect to the driver
                                      and that way making the current state of what I did not possible to be actually open-sourced (at all) - it's mostly useful experiment for understanding the communication protocol and that's it.

                                      so, that means such project to be really fully completed, it's like going from Europe to Taiwan (using that as example, because AEC were Taiwanese company and I am in Europe), but via the Moon. so, "Europe to Moon" trip is to implement it using WinDriver ​as proof-of-concept the communication protocol​ is reversed-engineered and fully-understood and then from "Moon to Taiwan" trip is write code to emulate the WinDriver environment, essentially that way remove that (annoying) dependency. now, that last part is totally feasible and not some far-fetched possibility, because of the following excellent article:

                                      "Direct Port I/O and Windows NT" by Dale Roberts
                                      Dr.Dobbs Journal, May 1996, p.14​
                                      in fact, I guess, AEC didn't know about that article and that's why they decided to develop their *.SYS using WinDriver and then the EXE is also stuck to (annoying)
                                      WinDriver-ways of speaking to the *.SYS. I cannot imagine anyone in their right mind for any reason to choose to use Jungo WinDriver ​adding with that just another "wrapping"-layer that serves no other real purpose than overhead. last, but not least - articles, like the aforementioned one shows of how high quality and great value were the computer magazines 30 years ago - something we no longer have.

                                      Comment

                                      • stefankd
                                        Member
                                        • Jul 2026
                                        • 23
                                        • Bulgaria

                                        #239
                                        more findings (which i am going to organize in separate points below) and a questions that someone reading here might be able to help with (it will be very appreciated):

                                        1. "the ICTEST.exe": it turned out it's doing the communication with the device in a different (you can say more efficient) way than how that's done in Windows. initially, it made my head spin not getting what's really going on, but in essence - in DOS (at least "ictest.exe") is reading back the nibbles in a way that results in 1st Least-Significant-Nibble (LSN) is read/returned and then the Most-Significant-Nibble (MSN), contrary to Windows, where it's MSN then LSN. actually, that difference is helpful to further understand the communication protocol and once realized it's very easy and trivial to translate QEMU log obtained from "ictest.exe" in DOS to the *.SYS Windows way. also, it's kinda more efficient causing 100-150 less lines on the QEMU log for each 50 read-backs.

                                        2. "the Hidden Menus" : indeed very intriguing, when run "ictest.exe" I can see in the Menus only options for:

                                        Code:
                                        User-Define IC Tester
                                        TTL IC Tester
                                        and "TTL" is few pre-defined 74-series common ICs to test like 74LS00, etc. however, in the disassembler-ed exe there is more:

                                        Code:
                                        DRAM IC Tester
                                        SRAM IC Tester
                                        SIMM Module Tester
                                        now going the rabbit-hole to try enabling those hidden menus, was unfortunately fruitless, because for the GUI they are using "Borland TurboVision" and the EXE is written in "Borland C++". so, it seems Borland were using TurboVision to promote Object-Oriented Programming (OOP) principles and I guess they are loading different Menus based on Virtual functions, etc. in short I cannot figure it out - and that is the question - if anyone has any ideas how such "hidden menus" can be enabled? one option to attack it I see is a lot of effort - I mean write some very simple TurboVision application in "Borland C++" with 2 menus that load based on some condition and then explore such disassembler-ed exe to which I have the source code to figure out how it's possible to patch and enable such TurboVision ​menus that appear when some condition is met.

                                        3. "the *.REZ files" : my investigation of point 2, made me realize that AEC *.REZ files are actually Borland TurboVision​ "TResourceFile", in fact they have the same signiture/magic-header-bytes of 'FBPR' that Borland documented on page 521 of "Borland Turbo Vision Version 2.0 Programming Guide 1992":

                                        https://archive.org/details/bitsaver.../n541/mode/2up

                                        TResourceFile

                                        During initialization, Init looks for a resource file header at the current
                                        position of the stream. The format of a resource file header is

                                        type

                                        TResFileHeader = record

                                        Signature: array[1..4] of Char;

                                        ResFileSize: Longint;

                                        IndexOffset: Longint;
                                        end;

                                        where Signature contains 'FBPR',.......
                                        so, AEC are re-using that well-defined file-container-format by Borland probably again using OOP priciples, i.e. inherit to their class the "TResourceFile​" and customized the behavior for their needs with virtual functions, etc. now that is new finding to the previous indispensable analysis of Ben “bushing” Byer of those *.REZ files:

                                        https://hackmii.com/2009/02/48uxp_sw/

                                        no matter that he wrote Parser in Python. however, that Parser is partial, because for example it cannot parse "
                                        TTLDEV.REZ" used by ICTEST.exe. anyway, it's probably very easy to parse those files using TurboVision​ libraries in "Borland C++"​.

                                        4. "the ICTEST Bitstream" : so, far I cannot find any evidence any Bitstream is uploaded to ​XC3030A, that means the Default one that's inside the FW is used. so, on top of the information from here:

                                        https://hackmii.com/2009/02/48uxp_sw/

                                        more specifically that there are 3 "default" Bitstreams - one hardcoded in the FW and 2 hardcoded in the EXE, I can add that each one of those 3 bitstreams is with size of 2778 bytes. that is not mentioned in that article, but it's very useful information when extracting those bitstreams.

                                        one more time to mention here that 48LV (FW 2.x) and even 48UXP(FW 4.x)​ contain the exact same Default Bitstream, which means all the functionality of ICTEST is possible with 48UXP(FW 4.x)​ as far as they did not blocked/removed some of the FW functions that allow Bit-banging and Pin-Voltage control from the Host with that Default Bitstream. BTW, in fact the aforementioned hidden "DRAM IC Tester, SRAM IC Tester, SIMM Module Tester" suggest quite complex operations are possible at least on 48/48LV with that Default Bitstream
                                        ​.

                                        Comment

                                        • stj
                                          Great Sage 齊天大聖
                                          • Dec 2009
                                          • 31944
                                          • Albion

                                          #240
                                          this is typical of the era when we went from win98 to win2000/xp,
                                          win98 and older where GUI's sitting on DOS7,
                                          much simpler to write stuff for.
                                          lots of older software was written in stuff like compiled pascal.
                                          turning nibbles into bytes in dos was just reading a nibble, rotating it sideways 4 times and xor'ing it with the next nibble!!
                                          try doing that on modern windows in 5 lines of code!!

                                          Comment

                                          Related Topics

                                          Collapse

                                          Working...