udo-munk / z80pack

A Zilog Z80 and Intel 8080 systems emulation
MIT License
158 stars 37 forks source link

imsaisim and probably others simulators do not accept plain binary files #265

Closed Selorax closed 1 year ago

Selorax commented 1 year ago

I wanted to load a program from plain binary file instead of toggling it in on switches, however it does not seem to load it, examine produces zeroes everywhere.

$ ./imsaisim -m 00 -x kill_the_bit.bin 

 #####    ###     #####    ###            #####    ###   #     #
#     #  #   #   #     #  #   #          #     #    #    ##   ##
#     # #     #  #     # #     #         #          #    # # # #
 #####  #     #   #####  #     #  #####   #####     #    #  #  #
#     # #     #  #     # #     #               #    #    #     #
#     #  #   #   #     #  #   #          #     #    #    #     #
 #####    ###     #####    ###            #####    ###   #     #

Release 1.37, Copyright (C) 1987-2021 by Udo Munk
IMSAI 8080 Simulation Release 1.18, 
Copyright (C) 2008-2021 by Udo Munk & 2018-2020 by David McNaughton

CPU speed is 2 MHz, CPU executes undocumented instructions
RAM size bank 0 is 64 KB
SIO 1A running at 9600 baud
SIO 2A running at 9600 baud
SIO 2B running at 2400 baud

Loader statistics for file kill_the_bit.bin:
START : FFFFH
END   : 0000H
LOADED: 0002H (2)

FrontPanel Simulator v2.1 Copyright (C) 2007-2015 by John Kichury

The file is 43 bytes long, produced like this:

$ xxd -p -r > kill_the_bit.bin
af 67 db ff 6f f9 af 81
c2 13 00 53 db ff 5f aa
c2 21 00 39 d2 06 00 78
07 47 d3 ff af 4f c3 06
00 a8 47 d3 ff af 67 2f
4f c3 00
^D

I know I was probably supposed to load intel hex, but it would be nice to be able to load plain binaries (specifying offset with some option switch) and things like that.

The code is taken from IMSAI 8080 System General Assembly and Test Instructions, converted to 8 byte wide hexdump by me for ease of entry into the machine.

I can't seem to make it run properly when I toggle it in with switches, but it could my mistake on some part, or emulation is just too fast or something.

Or, it seems that some registers are used unitialized, probably adding some instructions to set initial values for B and C should help. Is it know whether registers are supposed to be initialized to any particular value after CPU reset?

In meantime, another kill the bit game works fine.

udo-munk commented 1 year ago

Loading of binaries is not supported, use Intel hex or Mostek binary. An utility to convert a binary to intel hex is included in cpmsim/srctools.

It is possible to enter programs via the frontpanel, has been done numerous times. Of course you need to verify if every bit was entered correct.

CPU reset doesn't modify registers besides PC, see CPU manual.

Selorax commented 1 year ago

@udo-munk Thanks for the hint. The tool seem to work, though loading binaries w/o conversion would be nice too.

I didn't say that entering programs with front panel was impossible, in fact I loaded several programs, including that one. It's just it might be slightly tedious when you have to do it over and over again, if the program doesn't work.

Either way, it seems that the program from the article doesn't work on the simulator. Is it a problem with the program or with the simulator? Is there a debugger by any chance in addition to the front panel?

udo-munk commented 1 year ago

Loading binaries without load address has been tried and just causes issues, not supported. Use Intel hex or Mostek binary, both formats can be produced with the included assembler, or one can use conversion tools.

That is the nature of frontpanel machines, way back then people figured that very soon too and searched for solutions to avoid entering code via frontpanel. If you don't want to do it just load code into the machine directly.

Checkout the 1.38-dev release with "git checkout dev", the killbit program is included in the frontpanel machines. It has been entered manually as well as loaded and works, also the version using 16bit increment/decrement instructions.

With release 1.38-dev you can attach an ICE to every machine and use it for debbuging code. The frontpanel machines must be build without frontpanel then, because the machine can be controlled by either frontpanel or ICE. The z80sim machine always has the ICE attached because it is just a CPU and RAM, this machine is good for single stepping through some code and see what it does.

Selorax commented 1 year ago

Loading binaries without load address has been tried and just causes issues, not supported.

I agree, but, maybe if raw binary format is proposed then simulator might spit an error message such as: binary format requires a load address, you can specify it with something like --load-from 0x0000

I'm going to use hex format until then, but I think it would be nice to avoid double conversion. Though I can see you might want to avoid adding complexity to command line/input processing code (such as telling whether the format is binary or hex, by processing file name [.bin or .hex extension] or some additional command line switches)

Checkout the 1.38-dev release with "git checkout dev", the killbit program is included in the frontpanel machines.

Yeah, those works, as I tried before. I was talking about the different version, which uses IMSAI programmable LEDs which Altair does not have, instead of top eight address bits.

The frontpanel machines must be build without frontpanel then, because the machine can be controlled by either frontpanel or ICE.

I see, but it's kinda a bit pointless to debug kill the bit game with a debugger, if you can't even see the front panel.

udo-munk commented 1 year ago

The load routine is a common routine for all machines used for loading from the command line as well as from the configuation files. As I said, in releases before I tried loading of binaries without load address, that never worked well and just caused issues. Not supported and I'll not try again.

If you don't want to debug using an ICE then single step with the frontpanel, that allows to find bugs in software also. More tedious to do, because you have to read all informations from the LED's only, and this requires to understand the machine cyles and reading instructions in binary format. But then again you learn how it was to write and debug software for this early machines :)

ratboy666 commented 1 year ago

Selorax

Yes, entering programs from the front panel was tedious. And, still is tedious.

Back then I used an Altair... we would use the front panel to enter a bootstrap. The binary program was punched on a paper tape. The bootstrap loader would load what was called a "checksum loader". The checksum loader would load the program and run.

You see, it was so painful to enter with the front panel that we entered a bootstrap that did NOT do any error checking! Just the absoute minimum. The Altair tapes came punched in "Altair Binary". IMSAI tapes came in "Intel Hex". It was expected that you wuould be able to figure out the loading on your own.

IMSAI did give away software called SCS-1 (self contained system). This was a monitor, editor and assembler that would work in as little as 6K of memory. It was related to something called ALS-8. Udo does have the source for that on his site.

The idea is to develop a bootstrap for SCS-1 and then use THAT. Note that "back in the day" there were 10CPS teletypes (Model 33 machines) that were used as terminals and for data storage. Most of us preferred cassette tapes, using the 88-ACR or Tarbell interface. The 88-ACR was 30CPS... the Tarbell was 187CPS (or even faster).

On the 88-ACR we put a paper tape image! And something similar for the Tarbell.

Now, when/if you got a floppy disk, you would either "write patches to use it" (see deramp.com videos for examples), or implement a disk operating system.

That system was, widely CP/M 1.4 or 2.2

Digital Research would sell that to you on a IBM 3740 format disk, with drivers for the Intel MDS system. You were expected to be able to write and incorporate drivers (and deal with format conversion, if needed).

Once the computer hobbyist achieved that, s/he had a system that would be recognizable by people today. 

But, front panel operation is so painful that even MITS and IMSAI offered "PROM boards"; program a ROM and stick that in. On the Altair, typically we use 1K for ROM and 63K for RAM (and thus, you see a lot of "63K CP/M")

I use 4 x 256 byte ROMs in my Altair -- these are UBMON (256 byte monitor that enters data from terminal, punches to terminal, jumps to addresses), HDBL (256 byte ROM that boots from MITS Datakeeper - a 5+5MB hard disk), MBLE (multi boot loader, can load from paper tape/cassette), CDBL (can load from floppy disk 8 inch or minidisk).

These ROMs are not "period correct", but do represent "state of the art". For "period correct" I would use TURMON (the Altair "Turnkey Monitor").

Or, get practiced at entering bootstrap from the front panel!

Also, entering a small bootstrap to boot from cassette and using that to boot from disk was (fairly) common. I liked the Tarbell floppy controller "back in the day". It used the IBM 3740 format, and so could use the Digital Research CP/M media directly and the bootstrap could be entered from the front panel: here it is:

000400:  333 374 257 157 147 074 323 372 076 214 323 370 333 374 267 362 175 000  333 373 167 043 303 014  001

Some notes for you:

1 - The ALTAIR front panel had the switches grouped in 3... octal was prefered. We learned how to group our fingers to enter those. IMSAI used a grouping of 4, so hex, I guess. I used middle 3 fingers of my right hand... couldn't really do four fingers. So, I preferred octal, even on the IMSAI. 2 - This is 25 decimal bytes long. It reads and loads the first sector from a floppy disk on a Tarbell controller. 3 - This was used to load and run CP/M, at which point, further interaction just used the terminal!

Next is the entry pattern - I use three finger to swipe down, (clear to 000) put the 0..7 code and swipe up, repeat for 3 digits, then index finger for "deposit next"... timing myself, around 3 minutes to enter the Tarbell boot loader. That is with real switches -- on the emulator, in a window? 10 minutes? I haven't tried!

On Thu, 2023-01-12 at 22:44 -0800, Selorax wrote:

@udo-munk Thanks for the hint. The tool seem to work, though loading binaries w/o conversion would be nice too. I didn't say that entering programs with front panel was impossible, in fact I loaded several programs, including that one. It's just it might be slightly tedious when you have to do it over and over again, if the program doesn't work. Either way, it seems that the program from the article doesn't work on the simulator. Is it a problem with the program or with the simulator? Is there a debugger by any chance in addition to the front panel? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: <udo- @.***>

ratboy666 commented 1 year ago

Selorax

I started programming on these machines. Debugging? Not so much. There is NO breakpoint from the front panel. There is a single step, but too tedious. Pretty much, we debugged on the desk. simulate execution in our heads. In SCS-1, you can place up to 8 breakpoints, but they are painful (BREK clears all of them).

You also build the "skill" of reading 8080 object code. For example MOV dst, src is 01 ddd sss where the register (ddd or sss) is b:000 c:001 all the way to A:111 and, notice the grouping in 3 binary digits (aka octal). So, octal 123 would be MOV D,E (and in hex 43, but that is NOT as readable for us "front panel folks").

Life with ROMs is much more pleasant. Since the machine can be crashed by errant software... 176400 is the address to enter UBMON (or TURMON) -- FD00 for you hexians. Then.

STOP+RESET (not sure how you do that on the simulator... but raise STOP switch and, while it is raised, raise RESET, release both). enter the address 176400, EXAMINE then RUN.

That prompts with a "." on my terminal .

I can now edit memory:

.M0 000000 303 000001 003 000002 355 .?  .

J jumps to an address. This is much faster than using the font panel for everything. But still no "debugging". The Altair used LDAX D to toggle the upper address bits. Note that the instruction itself was in low memory... Only the execution of the LDAX D would present the address to the front panel during the instruction execution phase. So, killbits has LDAX D repeated 4 times. This gives the persistence of vision needed. It's all fake! Imagine trying to "debug" that...

The IMSAI has OUT FF to display data. This makes "debugging"... um... possible. The pattern output is latched. Note that the original kill the bit ... the IN FF switches are right underneath the upper address bits, so the alignment works!

And this was not even the most clever thing! That was Steve Dompier writing code to play "Fool in the Hill" -- using instruction timings and characteristics to produce music on an AM radio receiver.

https://www.youtube.com/watch?v=1FDigtF0dRQ

This cannot be "debugged" in the sense of breakpoints! Certainly not in the time critical parts.

And... the GUI style emulator will not do that... nor will my "Altair- Duino". Relying on accidental RF emissions... produced by a processor at a clock rate of 2MHz. The Altair-Duino will run the Processor Technology Music System.

On Fri, 2023-01-13 at 06:54 -0800, Selorax wrote:

Loading binaries without load address has been tried and just causes issues, not supported. I agree, but, maybe if raw binary format is proposed then simulator might spit an error message such as: binary format requires a load address, you can specify it with something like --load-from 0x0000 I'm going to use hex format until then, but I think it would be nice to avoid double conversion. Though I can see you might want to avoid adding complexity to command line/input processing code (such as telling whether the format is binary or hex, by processing file name [.bin or .hex extension] or some additional command line switches) Checkout the 1.38-dev release with "git checkout dev", the killbit program is included in the frontpanel machines. Yeah, those works, as I tried before. I was talking about the different version, which uses IMSAI programmable LEDs which Altair does not have, instead of top eight address bits. The frontpanel machines must be build without frontpanel then, because the machine can be controlled by either frontpanel or ICE. I see, but it's kinda a bit pointless to debug kill the bit game with a debugger, if you can't even see the front panel. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: <udo- @.***>

udo-munk commented 1 year ago

Now you have an idea how much fun that was to get the Z1 working with Cromix, no sources to look at, but the mighty frontpanel to figure out what the software is trying to do.

Selorax commented 1 year ago

@ratboy666

The Altair tapes came punched in "Altair Binary".

I didn't find any description of this format online, at least, easily.

. It used the IBM 3740 format, and so could use the Digital Research CP/M media directly and the bootstrap could be entered from the front panel

; Read one byte from 0xFC, ignore it
0100: DB FC    IN    FC
0102: AF       XRA   A
; Clear HL
0103: 6F       MOV   L, A
0104: 67       MOV   H, A
; Send 0x01 to 0xFA
0105: 3C       INR   A
0106: D3 FA    OUT   FA
; Send 0x8C to 0xF8
0108: 3E 8C    MVI   A, 8C
010A: D3 F8    OUT   F8
loop:
; Read a byte from 0xFC
010C: DB FC    IN    FC
010E: B7       ORA   A
; If top bit is set, go 0x7D
010F: F2 7D 00 JP    007D
; Read 0xFB and write from 0x0
0112: DB FB    IN    FB
0114: 77       MOV   M, A
0115: 23       INX   H
0116: C3 0C 01 JMP   loop
0119:

So, does it mean, that 0xFC has some sort of status, which tells when everything is ready, 0xFA sets number of sector to read (though why 0x01 instead of just 0?), and 0xF8 is some control input telling the disk to start reading? And sectors were at most 256 bytes, otherwise it would overwrite the loader.

Did I get it right?


;------------------------------;
; for IMSAI 8080, blink custom ;
; leds and address leds        ;
;------------------------------;
        org 0x0
0000: 31 00 01  lxi sp,0x100
; do not flash bottom addr LEDs
0003: 2E 00     mvi l,0
; but flash top address LEDs
0005: 26 01     mvi h,1
; LEDs take inverted input
0007: 0E 7F     mvi c,0x7F
        loop:
0009: 79        mov a,c
; update the LEDs
000A: D3 FF     out 0xff
000C: 11 00 0A  lxi d,0x0A00
000F: CD 1B 00  call delay
0012: 79        mov a,c
0013: 0F        rrc
0014: 4F        mov c,a
0015: 7C        mov a,h
0016: 07        rlc
0017: 67        mov h,a
0018: C3 09 00  jmp loop
; DE = delay amount
        delay:
001B: 1B        dcx d
; light address LEDs up
001C: 7E        mov a,m
001D: 7E        mov a,m
001E: 7E        mov a,m
001F: 7E        mov a,m
0020: 7E        mov a,m
0021: 7E        mov a,m
; are both d and e zero?
0022: 7A        mov a,d
0023: B3        ora e
0024: C2 1B 00  jnz delay
0027: C9        ret
0028:

I have written a light blinker for Imsai front panel, and tried it several times. Seems to work fine. But why doesn't the game which uses programmable LEDs works? This is still a mystery. Was it working on the real machine?

ratboy666 commented 1 year ago

On Fri, 2023-01-13 at 21:06 -0800, Selorax wrote:

@ratboy666

The Altair tapes came punched in "Altair Binary". I didn't find any description of this format online, at least, easily. . It used the IBM 3740 format, and so could use the Digital Research CP/M media directly and the bootstrap could be entered from the front panel ; Read one byte from 0xFC, ignore it 0100: DB FC IN FC 0102: AF XRA A ; Clear HL 0103: 6F MOV L, A 0104: 67 MOV H, A ; Send 0x01 to 0xFA 0105: 3C INR A 0106: D3 FA OUT FA ; Send 0x8C to 0xF8 0108: 3E 8C MVI A, 8C 010A: D3 F8 OUT F8 loop: ; Read a byte from 0xFC 010C: DB FC IN FC 010E: B7 ORA A ; If top bit is set, go 0x7D 010F: F2 7D 00 JP 007D ; Read 0xFB and write from 0x0 0112: DB FB IN FB 0114: 77 MOV M, A 0115: 23 INX H 0116: C3 0C 01 JMP loop 0119: So, does it mean, that 0xFC has some sort of status, which tells when everything is ready, 0xFA sets number of sector to read (though why 0x01 instead of just 0?), and 0xF8 is some control input telling the disk to start reading? And sectors were at most 256 bytes, otherwise it would overwrite the loader. Did I get it right?

Yes! the boot loader is 128 bytes, so loads sector 1 -- sectors started counting from 1. The last three bytes of the boot sector that was loaded is C3 hh ll which goes to the correct byte. That instruction will be located at 007D after loading. The code does make some "power-up" assumptions about the controller...especially about seeking... as a result (again afair -- last time I used this "for real" was 1982 or so) it worked on power-up but not after the drive had been used. The Altair absolute loader format is documented in the TURMON and UBMON code at deramp.com. Basically, address, 256 bytes and a checksum. This means that it is twice as dense as Intel Hex, but does need 8 bits.  Teletypes were basically 7 bit... so may not have always worked. Intel Hex only needs 6 bits (upper case, numeric and : and CR) -- and is pretty universal. There is a rather peculaiar format call 

MITS software came in the TURMON/UBMON load format. IMSAI tended to distribute binaries in Intel Hex format. A package like SCS-1 (self contained system 1) would take 20 minutes to load at 10cps! Martin Eberhardt wrote MAKEALT (make altair) which takes a HEX file and generates a TAP file -- in Altair absolute loader format, ready to be loaded with the "usual" MBLe ROM loader. But, I use MBLe to load a program HEXLOAD, which then loads Intel Hex (like the SCS-1 system).

;------------------------------; ; for IMSAI 8080, blink custom ; ; leds and address leds ; ;------------------------------; org 0x0 0000: 31 00 01 lxi sp,0x100 ; do not flash bottom addr LEDs 0003: 2E 00 mvi l,0 ; but flash top address LEDs 0005: 26 01 mvi h,1 ; LEDs take inverted input 0007: 0E 7F mvi c,0x7F loop: 0009: 79 mov a,c ; update the LEDs 000A: D3 FF out 0xff 000C: 11 00 0A lxi d,0x0A00 000F: CD 1B 00 call delay 0012: 79 mov a,c 0013: 0F rrc 0014: 4F mov c,a 0015: 7C mov a,h 0016: 07 rlc 0017: 67 mov h,a 0018: C3 09 00 jmp loop ; DE = delay amount delay: 001B: 1B dcx d ; light address LEDs up 001C: 7E mov a,m 001D: 7E mov a,m 001E: 7E mov a,m 001F: 7E mov a,m 0020: 7E mov a,m 0021: 7E mov a,m ; are both d and e zero? 0022: 7A mov a,d 0023: B3 ora e 0024: C2 1B 00 jnz delay 0027: C9 ret 0028:

Yes, mov a,m will give address activity! Consider this code:

; 10MCYC.ASM ; ; EXECUTE FOR 10 MILLION CYCLES. AT 2MHZ, THIS SHOULD TAKE 5 SECONDS, ; AND GIVES US A WAY TO "SPEED TEST" EMULATORS. ; ORG 100H ; MCYC: LXI H,0014H ; 10 TOP: LXI B,8200H ; 10 TOP2: DCR C ; 5 JNZ TOP2 ; 10 DCR B ; 5 JNZ TOP2 ; 10 DCR L ; 5 JNZ TOP ; 10 RET ; END

(cycle counts are in the comments). The idea is to execute 10 million cycles (5 seconds) on a 2MHz 8080. Your code seems fine! I had forgetten that the IMSAI LED at FF was inverted! I have a "killbit" game:

; ; KILL THE BIT GAME BY DEAN MCDANIEL, MAY 15, 1975 ; ; OBJECT: KILL THE ROTATING BIT. IF YOU MISS THE LIT BIT, ANOTHER ; BIT TURNS ON LEAVING TWO BITS TO DESTROY. QUICKLY ; TOGGLE THE SWITCH, DON'T LEAVE THE SWITCH IN THE UP ; POSITION. BEFORE STARTING, MAKE SURE ALL THE SWITCHES ; ARE IN THE DOWN POSITION.

ORG 0

LXI H,0 ;INITIALIZE COUNTER MVI D,080H ;SET UP INITIAL DISPLAY BIT LXI B,0EH ;HIGHER VALUE = FASTER BEG: LDAX D ;DISPLAY BIT PATTERN ON LDAX D ;...UPPER 8 ADDRESS LIGHTS LDAX D LDAX D DAD B ;INCREMENT DISPLAY COUNTER JNC BEG IN 0FFH ;INPUT DATA FROM SENSE SWITCHES XRA D ;EXCLUSIVE OR WITH A RRC ;ROTATE DISPLAY RIGHT ONE BIT MOV D,A ;MOVE DATA TO DISPLAY REG JMP BEG ;REPEAT SEQUENCE

END

To add in the IMSAI programmed output -- Just before LDAX D/LDAX D/LDAX D/LDAX D, (at label BEG) I would add in: MOV A,D/XRI 0FFH/OUT 0FFH -- unfortunately, adds 5 bytes to the code size.

That should put the information on both programmed i/o and address lines! 

I have written a light blinker for Imsai front panel, and tried it several times. Seems to work fine. But why doesn't the game which uses programmable LEDs works? This is still a mystery. Was it working on the real machine? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: <udo- @.***>

Selorax commented 1 year ago

I have found out, that kill the bit from IMSAI manual requires top switches to be set somewhere else than on all zeroes, to work. I have also made a modified version, which initializes all the registers, while the original leaves some of them unitialized.