• Please review our updated Terms and Rules here

Cromemco dazzler replica project

I will have a look at PAUSE again... I may have confused myself with which Dazzler register was being read.

I also started to write my own Z80 Dazzler library a while ago. I got as far as INITG and DOT. The difference was, I was targeting multiple Dazzler cards - so multiple contexts were being maintained (one for each initialised card).

The character bitmap is interesting. I am just adding some comments to the source for how the three bytes are stored for each character. Incidentally, it is slightly different to the description in the manual... That had me confused for a while. One line of pixels was always out by 1 bit...

Dave
 
I will have a look at PAUSE again... I may have confused myself with which Dazzler register was being read.

I also started to write my own Z80 Dazzler library a while ago. I got as far as INITG and DOT. The difference was, I was targeting multiple Dazzler cards - so multiple contexts were being maintained (one for each initialised card).

The character bitmap is interesting. I am just adding some comments to the source for how the three bytes are stored for each character. Incidentally, it is slightly different to the description in the manual... That had me confused for a while. One line of pixels was always out by 1 bit...

Dave
Just corrected my last post, the time base is the odd/even signal, not the vertical sync, which gives a better resolution.

I will have a look at the text implementation, but will try to finish the D+7A sound emulation first (it is so much easier to test new apps with an emulator...).
 
I stand by my comments...

The PAUSE subroutine reads variable VB197C - which is a stored copy of what was written to Dazzler I/O port $0E.

This port contains the ON/OFF bit (bit 7) and the highest seven address lines of the screen buffer address.

The code checks bit 7 of this stored port value (i.e. what was output to port $0E).

I would agree that if the subroutine directly read from the Dazzler's I/O port $0E, that would ascertain the odd/even frame.

Dave
 
I stand by my comments...

The PAUSE subroutine reads variable VB197C - which is a stored copy of what was written to Dazzler I/O port $0E.

This port contains the ON/OFF bit (bit 7) and the highest seven address lines of the screen buffer address.

The code checks bit 7 of this stored port value (i.e. what was output to port $0E).

I would agree that if the subroutine directly read from the Dazzler's I/O port $0E, that would ascertain the odd/even frame.

Dave
Ah, I see. So the PAUSE is finally CPU clock dependent. My fault, I am not familar enough with the Z80 assembler. Would make sense to use a real time base, though, but you are right!
 
Yes.

However, it uses that value of register A (the ON/OFF and high address bits) as a subsequent iterator - thus the timing is now dependent upon where the screen buffer address is in memory!

My guess is that they wanted to check whether the Dazzler was ON or OFF and bypass the delay if it was OFF?

However, the code doesn't test bit 7 and jump to the exit if the bit is clear (as I would have expected it to have done.

Even then, I still wouldn't have expected it to have used the register within the timing loop even if the Dazzler was ON.

I will do the calculation sometime to see what they should have done for a 0.1 second delay at 4 MHz given their code structure.

However, if the Dazzler is ON, it would make absolute sense to use the Dazzler hardware as a real time clock!

An enhancement we can make to fix their bug :)!

Dave
 
Added a few more (!) comments related to the storage format of the character bitmap tables.

Dave
 

Attachments

  • graphz80.zip
    11.9 KB · Views: 10
Yes.

However, it uses that value of register A (the ON/OFF and high address bits) as a subsequent iterator - thus the timing is now dependent upon where the screen buffer address is in memory!

My guess is that they wanted to check whether the Dazzler was ON or OFF and bypass the delay if it was OFF?

However, the code doesn't test bit 7 and jump to the exit if the bit is clear (as I would have expected it to have done.

Even then, I still wouldn't have expected it to have used the register within the timing loop even if the Dazzler was ON.

I will do the calculation sometime to see what they should have done for a 0.1 second delay at 4 MHz given their code structure.

However, if the Dazzler is ON, it would make absolute sense to use the Dazzler hardware as a real time clock!

An enhancement we can make to fix their bug :)!

Dave
Guess it makes sense that there are more iterations if the Dazzler is switched off, since the Dazzler acts as a bus master during the DMA cycle, which effectively temporarily stops the CPU. Using the content of the 0EH register shadow variable as start value for the A register probably is used as a kind of fine tuning to better match the 100ms delay (128 additional iterations for ON state, 256 additional iterations for OFF state).

Anyway, implementing a PAUSE routine in a Dazzler library from my point of view makes sense mostly if the Dazzler is activated. Where using the Dazzler status flags would be the better option.

I wonder how an active Dazzler influences the sound generation with a D+7A, which should be quite sensitive to droputs. My floppy controller requires the Dazzler to be switched off, otherwise data transfers will fail.
 
Now that is an interesting thought. Not sure why the screen buffer address is significant though.

I am wading about in the detail though! I need to comment the rest of the code first...

Dave
 
I'm releasing the code for the Dazzler Snake game on github:

I've completed adding joystick input & sound which work through the replica JS-1's we built.

After a lot of struggling to get the emulator environment up, the game also runs perfectly in z80pack with the Dazzler emulator. I just couldn't get anything to work well using the Windows build.. So I decided to finally give WSL a try, and it's working beautifully there! Now I need to update my z80pack to get your D+7A implementation.
 
I'm releasing the code for the Dazzler Snake game on github:

I've completed adding joystick input & sound which work through the replica JS-1's we built.

After a lot of struggling to get the emulator environment up, the game also runs perfectly in z80pack with the Dazzler emulator. I just couldn't get anything to work well using the Windows build.. So I decided to finally give WSL a try, and it's working beautifully there! Now I need to update my z80pack to get your D+7A implementation.

Hi,

I looked at the README.MD, but I don't see any keyboard controls for people that do not have a joystick.


.
 
Hi,

I looked at the README.MD, but I don't see any keyboard controls for people that do not have a joystick.


.
Yep it supports keyboard, when you start the game it'll ask you if you want keyboard or joystick, and 1 or 2 players.

Player 1 is WASD and Player 2 is IJKL
 
Hi,

My Altair 8800c is: TDL ZPU Z80 CPU board, 88-2SIOJP board, FDC+ board and DAZZLER II board ... I have 64K RAM, CP/M 2.2b ...

Ran the program on my DAZZLER II board ...

D0>SNAKE
DAZZLER SNAKE by nullvalue
JOYSTICK OR KEYBOARD CONTROL? [J,K]


I typed a "K" a few times, but the program never moves forward ???


.
 
Hi,

My Altair 8800c is: TDL ZPU Z80 CPU board, 88-2SIOJP board, FDC+ board and DAZZLER II board ... I have 64K RAM, CP/M 2.2b ...

Ran the program on my DAZZLER II board ...

D0>SNAKE
DAZZLER SNAKE by nullvalue
JOYSTICK OR KEYBOARD CONTROL? [J,K]


I typed a "K" a few times, but the program never moves forward ???


.

Ah I wonder if it needs to be patched to work with CP/M? I am using a CDOS BIOS call in order to retrieve the console input. I'll have to look up how that works in CP/M.
 
Actually no I take that back - I am reading port 0 for the console status, and if there is data waiting, read port 1 for console data... so I'm wondering if I should switch this over to a BIOS/system call instead?

According to the CDOS manual, looks like system call checks for input

1725251652300.png

Then this could would retrieve the character...


1725251735221.png

Anyone know if these calls are the same under CP/M? I would assume so, since I am using system calls to print lines/characters and he's seeing those under his environment. I'll give this a try tomorrow.
 
Last edited:
Hm,

See here: https://www.seasip.info/Cpm/bdos.html.

Did you mean BIOS or BDOS?

System call 11 (decimal) is present on CP/M. You just need to watch the status return, because they may be subtly different.

In your example, above:

A = 0 = character not typed.
A = -1 = character typed.

CP/M:

A = 0 = character not typed.
A NOT EQUAL TO ZERO = character typed.

If you check A for 0 for no character typed, and assume anything else means a character is typed, you should be good to go.

In terms of reading the character, BDOS code 128 does not exist in CP/M. Try BDOS function 6 (assuming this exists in CDOS of course).

Where possible, using the operating system functions (in a standardised way - i.e. the least common denominator between CDOS and CP/M) should guarantee the best 'audience' for your code.

Also, don't forget the different revision levels of CP/M. Go with the lowest revision of CP/M you can get away with for your application.

Dave
 
You're right I mean BDOS. Strangely enough, every copy of the CDOS manual I can find completely skips over function call 6.

I'll try it anyways, but if it doesn't work - is there some way to identify I am running inside CP/M vs CDOS? It seems like the system calls to read a console input (with echo) is the same for both operating systems, but I don't want to echo game control keys..
 
So I tested under CDOS with code 128 just to make sure my code is working, and it is... Switched it to code 6 and CDOS very much doesn't like that.. froze the system, printing out a repeated character to the console. However, it *should* work on CP/M.. so @wperko in the repository I added a "snakecpm.com" file - would you give that one a try?
 
Page 85 of https://deramp.com/downloads/mfe_ar...e/CDOS/Cromemco CDOS 0203 023-0036 197811.pdf indicates that the CP/M BDOS function number 6 is not supported.

Page 88 describes the 'compatibility' issue.

The assumption is that CP/M programs (with the odd exception as we have found out in not supporting function call 6) will run under CDOS but not (necessarily) the other way around.

The only way around this is to use symbol definitions and a feature of more 'professional' assemblers known as conditional assembly. This is the programmer's way of writing a program once and implementing features that are implementation dependent in a manageable way.

Dave
 
Page 85 of https://deramp.com/downloads/mfe_archive/010-S100 Computers and Boards/00-Cromemco/40-Cromemco Software/CDOS/Cromemco CDOS 0203 023-0036 197811.pdf indicates that the CP/M BDOS function number 6 is not supported.

Page 88 describes the 'compatibility' issue.

The assumption is that CP/M programs (with the odd exception as we have found out in not supporting function call 6) will run under CDOS but not (necessarily) the other way around.

The only way around this is to use symbol definitions and a feature of more 'professional' assemblers known as conditional assembly. This is the programmer's way of writing a program once and implementing features that are implementation dependent in a manageable way.

Dave

Thanks I'll just add a symbol definition for now and publish 2 builds. Pretty odd that of all CP/M system calls, they left out a very basic one..

EDIT: After trying on real hardware, using the system calls are noticeably slower (at least in CDOS) than the IN statement I was using before.. Looks like the Cromemco Macro Assembler does support conditional assembly, so I will add support CP/M through BDOS calls and keep the CDOS version the way I had it.
 
Last edited:
I'm releasing the code for the Dazzler Snake game on github:

I've completed adding joystick input & sound which work through the replica JS-1's we built.

After a lot of struggling to get the emulator environment up, the game also runs perfectly in z80pack with the Dazzler emulator. I just couldn't get anything to work well using the Windows build.. So I decided to finally give WSL a try, and it's working beautifully there! Now I need to update my z80pack to get your D+7A implementation.
See https://github.com/akueckes/Cromemco-Dazzler-RevD... I've packed the changes into z80pack-1.37_D7A_changes.zip. There is also a Makefile included for Cygwin, but the changes can be applied to the other Makefiles the same way. There is a version of PortAudio needed for compiling. For a Cygwin installation just use the Cygwin installer to select the PortAudio package. You also need a full X Windows package with Cygwin, and need to start it with "startxwin" in a seperate window before running anything graphical from z80pack. Also don't forget to set the DISPLAY environment variable properly to :0.0 prior to starting X Windows and z80pack.

Joystick is not yet implemented, since it shows to be a bit complicated with Cygwin (it needs to map the functionality to one of the numerous Windows multimedia frameworks). But it should be straight-forward with Linux using /dev/input/js*.

The file z80pack-1.37\iodevices\cromemco-dazzler.c is just complementary and holds some changes for the Dazzler emulation. You still can use the original Dazzler implementation.
 
Back
Top