VOGONS


Reply 60 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t
Predator99 wrote on 2020-07-01, 19:09:
I think I also need to revise my cabling. For EGA it makes sense to connect it in the order r, g, b, R, G, B, HSYNC, VSYNC With […]
Show full quote

I think I also need to revise my cabling. For EGA it makes sense to connect it in the order
r, g, b, R, G, B, HSYNC, VSYNC
With this you extract the color information in a very easy way from each byte read without performing any binary conversion in the program:
https://upload.wikimedia.org/wikipedia/common … 2/EGA_Table.svg

Hi BreakPoint,

when setting up you cable, please use the following wiring:

Analyzer Channel - Card connector
Channel 1 - 5 B
Channel 2 - 4 G
Channel 3 - 3 R
Channel 4 - 6 Gint
Channel 5 - 2 Rint
Channel 6 - 7 Bint
Channel 7 - 8 Hsync
Channel 8 - 9 Vsync
I dont understand the logic behind it and it took me some time to get behind this....but by doing so you get the EGA-color number from the captured byte simply by masking out the HSYNC/VSYNC channel (CH7/CH8):
color = (captured_value AND VAL("&B00111111")).
So for me the order is somehow reversed but it works. Should be the same for other programming languages 😉 Saves a lot of CPU-time and programming effort...

Thanks!

...EDIT: Noticed minor mistake in cabling, corrected!

Last edited by Predator99 on 2020-07-11, 21:10. Edited 1 time in total.

Reply 61 of 212, by BreakPoint

User metadata
Rank Member
Rank
Member

You can easily calculate color component by multiplying hexadecimal 0x55 by 2 bit EGA color component. So EGA 00 is 0. EGA 01 is 0x55, EGA 10 = 0xAA, EGA 11 = 0xFF. So in general cable wiring does not really matter. You can get color by using simple bit operations.
I spent some time with sigrok. It looks like there is not much documentation on API. I'll try to do some reverse-engineering of PulseView and CGI when i have some free time. But actually your results are good proof of concept.

My CPU collection - Looking for hardware in Ukraine - Ukraine vintage PC forum

Reply 62 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t
BreakPoint wrote on 2020-07-04, 18:01:

You can easily calculate color component by multiplying hexadecimal 0x55 by 2 bit EGA color component. So EGA 00 is 0. EGA 01 is 0x55, EGA 10 = 0xAA, EGA 11 = 0xFF. So in general cable wiring does not really matter. You can get color by using simple bit operations.

Thats true, but you dont need this effort when the bits are directly in the correct order.

BreakPoint wrote on 2020-07-04, 18:01:

I spent some time with sigrok. It looks like there is not much documentation on API. I'll try to do some reverse-engineering of PulseView and CGI when i have some free time. But actually your results are good proof of concept.

Did you see this?
https://sigrok.org/wiki/Developers

Maybe its even possible to make a "protocol decoder" which pops up with a graphics screen?

Reply 63 of 212, by Benedikt

User metadata
Rank Oldbie
Rank
Oldbie

A Sigrok protocol decoder would certainly be possible, but I strongly doubt that it would be usable for anything but still frames. The Python code it probably not even remotely fast enough.

You could speed up you own code, though, by reading blocks of data from stdin and iterating over it. Byte-wise I/O can be abysmally slow.

Reply 64 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t
Benedikt wrote on 2020-07-09, 14:59:

You could speed up you own code, though, by reading blocks of data from stdin and iterating over it. Byte-wise I/O can be abysmally slow.

Yes indeed, I also had this idea. But for this the C# part needs to be modified - I dont know how to do this.

I think QB64 is as slow as Python. For somebody with average C# skills it should be no problem to transfer my little program and implement the reading of blocks of data over stdin if still to slow...

Reply 65 of 212, by Benedikt

User metadata
Rank Oldbie
Rank
Oldbie

I still have some rudimentary C++ and SDL code for the same task since I had virtually the same project idea in 2018 but then abandoned it before it got anywhere.
I should really dig that up sometime.

Reply 66 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t

As requested my QB64 source for EGA. Cable needs to be (I made a minor mistake in my above post...also corrected):

Analyzer Channel - Card connector
Channel 1 - 5 B
Channel 2 - 4 G
Channel 3 - 3 R
Channel 4 - 6 Gint
Channel 5 - 2 Rint
Channel 6 - 7 Bint
Channel 7 - 8 Hsync
Channel 8 - 9 Vsync

Best to try:

1) Start a 320x200 game with animation, e.g. populous. Easy to start from autoexec.bat without monitor attached.

2) create a 10 seconds data file "EGA.bin" with
sigrok-cli.exe" -d fx2lafw --time 10s -O binary --config "samplerate=24 MHz" > EGA.bin

3) replay this file with:
type EGA.bin | sigrok-EGA.exe

For other modes than 320x200 you need to exchange two lines in the program, see comments below.

Thats all...with this little program you can make the nice 64-color screenshots I posted above, including animation...:

--- sigrok-EGA.BAS

DECLARE LIBRARY "std_wrapper"
FUNCTION getchar_stdin& ()

END DECLARE

42 SCREEN _NEWIMAGE(1700, 700, 12)
50 value = getchar_stdin&
HSYNC = 0
VSYNC = 0

REM Read SYNCS from value
211 IF ((value AND 128) <> 0) THEN VSYNC = 1
212 IF ((value AND 64) <> 0) THEN HSYNC = 1

REM Wait for VSYNC
IF VSYNC = 0 THEN vsyncc = 0: GOTO 230
IF VSYNC = 1 THEN vsyncc = vsyncc + 1

REM This is different for different modes and cards:
REM There are "false" VSYNCS, therefore it must be at least 20 bytes long to be accepted.
REM Remove this if you dont see anything, it will disable screen refresh.
IF VSYNC = 1 AND vsyncc > 20 THEN y = 0: LOCATE 22, 1: PRINT TIME$: GOTO 50

230
REM decode EGA color: Mask out HSYNC/VSYNC
color1 = (value AND VAL("&B00111111"))

REM Next activates flicker-free for 320x200, other modes will not work!
PSET ((319 / 1070) * (x - 305), y), color1

REM Uncomment below and comment above to see every mode (unfiltered)
REM PSET (x, y), color1

250 IF HSYNC = 1 THEN Ref_len = Ref_len + 1
252 IF HSYNC = 0 THEN Ref_len = 0
260 IF HSYNC = 1 AND x > 700 AND (Ref_len > 30) THEN PSET (x, y), 5: y = y + 1: x = 0
x = x + 1

700 GOTO 50

----std_wrapper.h (put in your QB64 root-DIR)
#include <cstdio>

int getchar_stdin(){
unsigned char getChar;
getChar = fgetc (stdin);
return (int)getChar;
}

void write_string(char * s){
printf("%s", s);
return ;
}

Attachments

  • pop1.jpg
    Filename
    pop1.jpg
    File size
    197.79 KiB
    Views
    980 views
    File license
    Fair use/fair dealing exception

Reply 67 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t

And for the lazy ones:
sigrok-ega.exe and a 10 seconds sample file capttured with the logic analyzer. To replay extract both and type:

type EGA.bin | sigrok-EGA.exe

Filename
EGA.rar
File size
1.84 MiB
Downloads
52 downloads
File license
Fair use/fair dealing exception
Filename
sigrok-EGA.rar
File size
495.59 KiB
Downloads
46 downloads
File license
Fair use/fair dealing exception

Reply 68 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t

Other nice demo capture: Commander Keen 5

I am quite sure this will speed up to real-time if somebody is able to transfer my 20-lines QB64 Program to C++............

type keen5b.bin | sigrok-EGA.exe

Attachments

  • Filename
    keen5b.part002.rar
    File size
    4 MiB
    Downloads
    43 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    keen5b.part003.rar
    File size
    4 MiB
    Downloads
    41 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    keen5b.part004.rar
    File size
    4 MiB
    Downloads
    40 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    keen5b.part005.rar
    File size
    1.77 MiB
    Downloads
    43 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    keen5b.part001.rar
    File size
    4 MiB
    Downloads
    44 downloads
    File license
    Fair use/fair dealing exception
Last edited by Predator99 on 2020-07-12, 10:56. Edited 1 time in total.

Reply 69 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t

s

keen5.jpg
Filename
keen5.jpg
File size
294.35 KiB
Views
956 views
File license
Fair use/fair dealing exception
CC.jpg
Filename
CC.jpg
File size
262.53 KiB
Views
927 views
File license
Fair use/fair dealing exception
Last edited by Predator99 on 2020-07-15, 08:35. Edited 1 time in total.

Reply 70 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t

Wow...one download... 🙁

I have made some benchmarks (i7-4790@3.6 GHz) to see where the bottleneck is.
When reading from STDIN in the the c library, I tested if it makes a difference to read byte-wise or block-wise (1000 bytes at once).

With...
getChar = fgetc (stdin);

and also with
fgets(buffer, 1000, stdin);

It takes 8 seconds to read 240.000.000 bytes from stdin - whichs corresponds to 10 seconds of data using a 24MHz capture. This in a simple loop without any processing of the data .

So this makes no difference on this level.

When doing the byte-wise transfer from the c library to QB64, it also takes 8 seconds to transfer the 240.000.000 bytes, without any further processing. So this is no bottleneck.

Including the rather simple data processing and drawing of the image in QB64, it takes 42 seconds to process 240.000.000 bytes.

--> My conclusion: QB64 is too slow. With all calculations done in c++ it will work in real-time, also when using STDIN.

Reply 71 of 212, by root42

User metadata
Rank l33t
Rank
l33t

Yeah, I would guess that stdin itself is buffered. So reading bytes or blocks probably doesn't make any difference. Using any language (compiled or JIT) other than BASIC will probably lead to performance gains. Also parallelizing some of the tasks/loops will help as well. I guess this is a task that can easily scale to multiple cores if several scanlines are buffered.

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 72 of 212, by root42

User metadata
Rank l33t
Rank
l33t
Predator99 wrote on 2020-07-04, 21:40:
BreakPoint wrote on 2020-07-04, 18:01:

You can easily calculate color component by multiplying hexadecimal 0x55 by 2 bit EGA color component. So EGA 00 is 0. EGA 01 is 0x55, EGA 10 = 0xAA, EGA 11 = 0xFF. So in general cable wiring does not really matter. You can get color by using simple bit operations.

Thats true, but you dont need this effort when the bits are directly in the correct order.

In correct order for a 4 bit output, yes. But BreakPoint suggests to do this transform for an RGB output. Which makes sense when using not a BASIC program, but something that uses e.g. SDL with an RGB surface.

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 73 of 212, by Predator99

User metadata
Rank l33t
Rank
l33t

root_42 from dosreloaded.de was so kind to transfer my code to c++ within a few minutes..!

https://dosreloaded.de/forum/index.php?thread … 6257#post106266

He already created a video:
https://www.youtube.com/watch?v=JgYpNU9yGyY&feature=youtu.be
Looks fantastic!

I think I will focus on the discussion there now to get it forward...

Reply 75 of 212, by root42

User metadata
Rank l33t
Rank
l33t
Predator99 wrote on 2020-07-15, 18:51:

root_42 from dosreloaded.de was so kind to transfer my code to c++ within a few minutes..!

Oh man, that guy sounds like a really cool dude! I wish I could meet him at some point!

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 76 of 212, by Pierre32

User metadata
Rank Oldbie
Rank
Oldbie
imi wrote on 2020-07-15, 19:01:

awesome :3

I really can't help discussing much, just watch in awe ^^

Same! I'm sure there are plenty of us who can't contribute but are really enjoying watching the progress. @Predator99 the view count on your embedded images is a better indication of how many people are watching with interest.

Reply 77 of 212, by Deksor

User metadata
Rank l33t
Rank
l33t

One thing I noticed though is that I don't see the source code in your github, only the executable. Am I missing something or did you upload the wrong file ?

Trying to identify old hardware ? Visit The retro web - Project's thread The Retro Web project - a stason.org/TH99 alternative

Reply 78 of 212, by root42

User metadata
Rank l33t
Rank
l33t
Deksor wrote on 2020-07-16, 16:39:

One thing I noticed though is that I don't see the source code in your github, only the executable. Am I missing something or did you upload the wrong file ?

I uploaded the wrong file. It's corrected now.

YouTube and Bonus
80486DX@33 MHz, 16 MiB RAM, Tseng ET4000 1 MiB, SnarkBarker & GUSar Lite, PC MIDI Card+X2+SC55+MT32, OSSC

Reply 79 of 212, by Deksor

User metadata
Rank l33t
Rank
l33t

I improved your program because the scaling was totally off 😀

Now the overscan area that gets colored is entirely shown, the rest is cut.

Sigrok_scaled.png
Filename
Sigrok_scaled.png
File size
13.81 KiB
Views
777 views
File license
Fair use/fair dealing exception
#include <stdio.h>
#include <stdlib.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_surface.h>

#define IMG_WIDTH 376
#define IMG_HEIGHT 247

void pset( SDL_Surface *surface,
unsigned int x,
unsigned int y,
unsigned char color
)
{
Uint32 pixel =
( ((color & (1 << 0)) << 1) + ((color & (1 << 3)) >> 3)) * 0x000055 // R
+ (((color & (1 << 1)) >> 0) + ((color & (1 << 3)) >> 3)) * 0x005500 // G
+ (((color & (1 << 2)) >> 1) + ((color & (1 << 3)) >> 3)) * 0x550000 // B
;

Uint32 *target_pixel = surface->pixels + y * surface->pitch +
x * sizeof *target_pixel;
*target_pixel = pixel;
}

int main(int argc, char** argv) {
int new_frame = 0;
unsigned char value, color1;
int hsync = 0, vsync = 0;
int frame = 0;
unsigned int vsyncc = 0, ref_len = 0;
unsigned int x = 0, y = 0;

SDL_Window *window; // Declare a pointer

SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2

// Create an application window with the following settings:
window = SDL_CreateWindow(
"SIGROK2EGA",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
376,
247,
SDL_WINDOW_SHOWN
);

// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}

SDL_Surface *surface =
SDL_CreateRGBSurface(0, IMG_WIDTH, IMG_HEIGHT, 32, 0, 0, 0, 0);
if (surface == NULL) {
SDL_Log("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
exit(1);
Show last 66 lines
	}
SDL_Surface *screen = SDL_GetWindowSurface(window);
if (screen == NULL) {
SDL_Log("SDL_GetWindowSurface() failed: %s", SDL_GetError());
exit(1);
}

while(!feof(stdin)) {
value = fgetc(stdin);
vsync = value & 128;
hsync = value & 64;
if( vsync == 0 ) {
vsyncc = 0;
new_frame = 0;
} else {
vsyncc++;
if( vsyncc > 20 ) {
vsyncc = 0;
y = 0;
// this means a new frame?
if( !new_frame ) {
new_frame = 1;
frame++;
printf("frame %u\n", frame);
// char fn[255];
// snprintf(fn, 255, "public_html/public/ega-%u.bmp", frame);
// SDL_SaveBMP(surface, fn);
SDL_BlitSurface(surface, NULL, screen, NULL);
SDL_UpdateWindowSurface(window);
SDL_Event e;
if (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
break;
}
}
}
else {

}
}
continue;
}
color1 = value & 0x3F;
int x_scaled = 319.0/1070.0*(x-184);
int y_scaled = y -13;
if( x_scaled >= 0 && x_scaled < IMG_WIDTH && y_scaled >= 0 && y_scaled < IMG_HEIGHT ) {
pset(surface, x_scaled, y_scaled, color1);
}
x++;
if( hsync ) {
ref_len++;
if( ref_len > 30 && x > 700 ) {
//pset(surface, x, y, 5);
y++;
x = 0;
}
} else {
ref_len = 0;
}
}

SDL_DestroyWindow( window );
SDL_Quit();

return 0;
}

Trying to identify old hardware ? Visit The retro web - Project's thread The Retro Web project - a stason.org/TH99 alternative