nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 25 May 2024 09:58



Reply to topic  [ 32 posts ]  Go to page Previous  1, 2, 3  Next
XORLib - игровая либа для старой школы ;) 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Частота дискретизации вот в этой картинке составляет 14.31818 МГц (тут для простоты опущено поле справа и синхросигнал - видны только "color burst" в начале каждой строки и 640 мнохромных пикселов, в которых NTSC-телек улавливает цветные пикселы с эффективным горизонтальным разрешением 160 пикселов в строке).

Code:
Затравка (9 иголок "color burst") идёт с частотой 3.57954 МГц:
11001100110011001100110011001100110000000000...
Сигнал с частотой 7.15909 МГц должен в идеале показываться серым:
1010101010101010101010...
Белая строка пикселов это последовательность единиц:
11111111111111...
А чёрная строка пикселов это последовательность нулей:
00000000000000...

Для более точной работы наверное надо сделать частоту дискретизации в 2 раза больше - 28.63636 МГц (чтобы точно не упустить никаких мелочей).

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


11 Jan 2023 21:47
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Shaos wrote:
Image



Вот пока начал с яркости:


Attachments:
cgatrick_xbm015_gray.jpg
cgatrick_xbm015_gray.jpg [ 89.15 KiB | Viewed 20265 times ]

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973
12 Jan 2023 01:09
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
И ещё одна старая картинка с 6й страницы этого топика:

Image

Image

Image

Пропускаем монохром (самый первый выше) через цифровой фильтр IIR:

Attachment:
cgatrick_xbm025_gray.jpg
cgatrick_xbm025_gray.jpg [ 94.85 KiB | Viewed 20265 times ]

Теперь осталось добавить цвет :mrgreen:

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


12 Jan 2023 01:11
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Вроде подогнал :)


Attachments:
cgatrick_xbm025_color.jpg
cgatrick_xbm025_color.jpg [ 176.65 KiB | Viewed 20254 times ]
cgatrick_xbm015_color.jpg
cgatrick_xbm015_color.jpg [ 170.01 KiB | Viewed 20254 times ]

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973
12 Jan 2023 02:38
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
А вот все 15 цветов полученные программно (напомню, что не 16 потому, что два серых одинаковые):

Attachment:
cgatrick_colors.jpg
cgatrick_colors.jpg [ 44.58 KiB | Viewed 20245 times ]

Это очень похоже на композитные цвета в DOSBox сдвинутые на 60 градусов (возможно DOSBox считает по такому же алгоритму, что и я):

----->Image

А вот как было на почившем сониковском телеке:



Получается сейчас уже можно городить порт XORLib на Linux с настоящими композитными цветами :roll:

P.S. Вот только режим 400 строк так просто не сымитировать, хотя наверное можно попробовать...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


12 Jan 2023 03:21
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
А теперь посмотрим как может выглядеть экран ZX-спектрума на программно сымитированной композитной картинке :)

Attachment:
zx1.jpg
zx1.jpg [ 17.13 KiB | Viewed 20330 times ]


На большом телеке напомню было так:


_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


12 Jan 2023 04:23
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Ну т.е. в-принципе похоже получается:

Attachment:
zx2.jpg
zx2.jpg [ 104.43 KiB | Viewed 20330 times ]



_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


12 Jan 2023 04:25
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Attachment:
zx6.jpg
zx6.jpg [ 60.39 KiB | Viewed 20324 times ]



_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


12 Jan 2023 04:31
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Ну а теперь самое главное - берём программу генерации косых линий:

 colodiag.c
Code:
/* colodiag.c - A.A.Shabarshin (October 2022) */

/* THIS PUBLIC DOMAIN SOURCE CODE IS PROVIDED AS IS */

#include "xorlib.h"

int main()
{

 int i,y;
 unsigned char *p;

 xoinit(XOMODE_160x200_COL15); /* gray colors 5 and 10 are identical */

/*
 0 - Default composite mode colors
 1 - Similar to CGA composite mode colors
 2 - Similar to Tandy composite mode colors
 3 - Similar to PCjr composite mode colors
*/
 xopalette(0);

 for(y=0;y<200;y++)
 {
   p = xodirectline(y);
   if(y<2||y>=198)
   {   /* white frame */
       for(i=0;i<80;i++) p[i] = 0xFF;
       continue;
   }
   p[0] = 0xF0;
   p[79] = 0x0F;

   if(y>=2 && y<14) for(i=1;i<79;i++) p[i]=0x00;
   if(y>=15 && y<26) for(i=1;i<79;i++) p[i]=0x11;
   if(y>=27 && y<38) for(i=1;i<79;i++) p[i]=0x22;
   if(y>=39 && y<50) for(i=1;i<79;i++) p[i]=0x33;
   if(y>=51 && y<62) for(i=1;i<79;i++) p[i]=0x44;
   if(y>=63 && y<74) for(i=1;i<79;i++) p[i]=0x55;
   if(y>=75 && y<86) for(i=1;i<79;i++) p[i]=0x66;
   if(y>=87 && y<98) for(i=1;i<79;i++) p[i]=0x77;
   if(y>=99 && y<110) for(i=1;i<79;i++) p[i]=0x88;
   if(y>=111 && y<122) for(i=1;i<79;i++) p[i]=0x99;
   if(y>=123 && y<134) for(i=1;i<79;i++) p[i]=0xAA;
   if(y>=135 && y<146) for(i=1;i<79;i++) p[i]=0xBB;
   if(y>=147 && y<158) for(i=1;i<79;i++) p[i]=0xCC;
   if(y>=159 && y<170) for(i=1;i<79;i++) p[i]=0xDD;
   if(y>=171 && y<182) for(i=1;i<79;i++) p[i]=0xEE;
   if(y>=183 && y<194) for(i=1;i<79;i++) p[i]=0xFF;

   for(i=y+5;i<y+35;i++) xopixel(i,y,i&1);   
   
   for(i=y+70;i<y+170;i++) xopixel(i,y,0);
   for(i=y+170;i<y+270;i++) xopixel(i,y,i&1);
   for(i=y+270;i<y+370;i++) xopixel(i,y,1);
   
   for(i=y+405;i<y+435;i++) xopixel(i,y,(i&1)?0:1);
 }

 return 0;
}

Как оно было на телеке:

Image

И как выглядит будучи программно сгенерённым на компьютере:


Attachments:
diags.png
diags.png [ 129.97 KiB | Viewed 20310 times ]

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973
12 Jan 2023 04:46
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
Вобщем я вот чего думаю - вместо того чтобы экспериментировать на реальном железе, наблюдая в реальности во что может превратиться та или иная последовательность пикселов... надо написать софт для ПЦ, который будет имитировать "обманувшийся" телек NTSC...

Обычно здесь меня упрекают в чрезмерном пристрастии к эмуляции... :roll:
А тут и ты сам вдруг к этой стезе склонился! :o
А как же "трюЪ железное" видео? :lol:

_________________
iLavr


12 Jan 2023 07:05
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Ну железяка у меня уже есть :lol:

В данном случае точная имитация композитного экрана нужна исключительно для ускорения процесса разработки :roll:

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


12 Jan 2023 09:25
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 08:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
В данном случае точная имитация композитного экрана нужна исключительно для ускорения процесса разработки :roll:

А, собственно эмуляция, и различные расчеты именно с этой целью и нужны. :wink:

_________________
iLavr


12 Jan 2023 09:41
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Автор картинки откуда я взял вот этот кусочек:
Image
запрещает её использование где либо: https://www.deviantart.com/howling/art/BoxedTown-2-9534561

Поэтому я экспериментирую с этой картинкой только в пределах этого форума - приаттачиваю архив с XBM файлом, используемой для сборки конвертера - XBM соответствует вот этой монохромной картинке:

Image

А исходный текст самого конвертера можно найти под спойлером:

 composite.c
Code:
/* Created by Alexander "Shaos" Shabarshin in January 2023
   and immediately turned into PULIC DOMAIN

   http://xorlib.com

   Build: gcc composite.c -o composite -lpng -lm
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <png.h> /* libpng */

/*
#define COLORBARS
*/

#include "cgatrick_xbm025.xbm"
#define IMGARRAY cgatrick_xbm025_bits

#define OFFSET 96
#define DX 736
#define DY 200

#define FILTERS 3

/*
./mkfilter -Bu -Lp -o 3 -a 0.0469 0.0000000000e+00 -l
*/

#define NZEROS 3
#define NPOLES 3
#define GAIN   4.1115485147e+02

double xv[FILTERS][NZEROS+1], yv[FILTERS][NPOLES+1];

static double filterstep(double v, int i)
{
        xv[i][0] = xv[i][1]; xv[i][1] = xv[i][2]; xv[i][2] = xv[i][3];
        xv[i][3] = v / GAIN;
        yv[i][0] = yv[i][1]; yv[i][1] = yv[i][2]; yv[i][2] = yv[i][3];
        yv[i][3] =   (xv[i][0] + xv[i][3]) + 3 * (xv[i][1] + xv[i][2])
                     + (  5.5347203431e-01 * yv[i][0]) + ( -1.9855726416e+00 * yv[i][1])
                     + (  2.4126432180e+00 * yv[i][2]);
        return yv[i][3];
}

void filtersclean(void)
{
  int i,j;
  for(i=0;i<FILTERS;i++)
  {
     for(j=0;j<=NZEROS;j++)
     {
       xv[i][j] = 0.0;
       yv[i][j] = 0.0;
     }
  }
}

int savepng(char* filename, int width, int height, unsigned char* data)
{
   /* Assume that it's RGB888 image */
   int bitdepth = 8;
   int colortype = PNG_COLOR_TYPE_RGB;
   int transform = PNG_TRANSFORM_IDENTITY;
   int i = 0;
   int r = 0;
   FILE* fp = NULL;
   png_structp png_ptr = NULL;
   png_infop info_ptr = NULL;
   static png_bytep row_pointers[1024];
   if(NULL == data) { r = -1; goto endlabel; }
   if(!filename || !filename[0]) { r = -2; goto endlabel; }
   if(NULL == (fp = fopen(filename, "wb"))) { r = -4; goto endlabel; }
   if(NULL == (png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) { r = -5; goto endlabel; }
   if(NULL == (info_ptr = png_create_info_struct(png_ptr))) { r = -6; goto endlabel; }
   png_set_IHDR(png_ptr, info_ptr, width, height, bitdepth,
                colortype,          /* PNG_COLOR_TYPE_{GRAY, PALETTE, RGB, RGB_ALPHA, GRAY_ALPHA, RGBA, GA} */
                PNG_INTERLACE_NONE, /* PNG_INTERLACE_{NONE, ADAM7 } */
                PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE);
   for(i = 0; i < height; ++i) row_pointers[i] = data + i*width*3;
   png_init_io(png_ptr, fp);
   png_set_rows(png_ptr, info_ptr, row_pointers);
   png_write_png(png_ptr, info_ptr, transform, NULL);
 endlabel:
   if(NULL != fp)
   {
     fclose(fp);
     fp = NULL;
   }
   if(NULL != png_ptr)
   {
     if(NULL == info_ptr) r = -7;
     png_destroy_write_struct(&png_ptr, &info_ptr);
   }
   return r;
}

double shiftedcos[8],shiftedsin[8];

unsigned char* img;

#define PHASEOFFSET 200

int main(int argc, char** argv)
{
  int x,y,i,j,m,r,g,b,phase=0;
  double d,dy,du,dv;
  unsigned char c,by;
  img = (unsigned char*)malloc(1288*1008*3);
  if(img==NULL) return -1;
  if(argc>1) phase=atoi(argv[1]);
  for(i=0;i<8;i++)
  {
    d = M_PI*(phase+PHASEOFFSET)/180.0;
    shiftedcos[i] = cos(M_PI/4.0*i+d);
    shiftedsin[i] = sin(M_PI/4.0*i+d);
  }
#define CLAMP(x) if(x<0) x=0; if(x>255) x=255
#define GETRGB(r,g,b,y,u,v) r=y+1.13983*v;g=y-0.39465*u-0.58060*v;b=y+2.03211*u
  for(y=0;y<1008;y++)
  {
    if(y<4 || y>=1004)
    {
       memset(&img[y*1288*3],0,1288*3);
       continue;
    }
    filtersclean();
    i = (y-4)/5*DX/8+OFFSET/8;
    for(x=0;x<1280;x+=16)
    {
       by = IMGARRAY[i++];
       m = 1;
       for(j=0;j<8;j++)
       {
#ifndef COLORBARS
          if(by&m)
               d = 0.0;
          else d = 1.0;
#else
          switch(j)
          {
             case 0: case 4: d=((x/80)&8)?1.0:0.0; break;
             case 1: case 5: d=((x/80)&4)?1.0:0.0; break;
             case 2: case 6: d=((x/80)&2)?1.0:0.0; break;
             case 3: case 7: d=((x/80)&1)?1.0:0.0; break;
          }
#endif
          dy = 255*filterstep(d,0);
          dv = 255*filterstep(d*shiftedcos[(x+j+j)&7],1);
          du = 255*filterstep(d*shiftedsin[(x+j+j)&7],2);
          GETRGB(r,g,b,dy,du,dv);
          CLAMP(r);CLAMP(g);CLAMP(b);
          img[(y*1288+x+j*2)*3] = r;
          img[(y*1288+x+j*2)*3+1] = g;
          img[(y*1288+x+j*2)*3+2] = b;
          dy = 255*filterstep(d,0);
          dv = 255*filterstep(d*shiftedcos[(x+j+j+1)&7],1);
          du = 255*filterstep(d*shiftedsin[(x+j+j+1)&7],2);
          GETRGB(r,g,b,dy,du,dv);
          CLAMP(r);CLAMP(g);CLAMP(b);
          img[(y*1288+x+j*2+1)*3] = r;
          img[(y*1288+x+j*2+1)*3+1] = g;
          img[(y*1288+x+j*2+1)*3+2] = b;
          m <<= 1;
       }
    }
    for(j=0;j<8;j++)
    {
       dy = 255*filterstep(0,0);
       dv = 255*filterstep(0,1);
       du = 255*filterstep(0,2);
       GETRGB(r,g,b,dy,du,dv);
       CLAMP(r);CLAMP(g);CLAMP(b);
       img[(y*1288+1280+j)*3] = r;
       img[(y*1288+1280+j)*3+1] = g;
       img[(y*1288+1280+j)*3+2] = b;
    }
  }
  savepng("composite.png",1288,1008,img);
  free(img);
  return 0;
}


Для фильтрации я использую вот такой фильтр низкой частоты, сгенерированный программой mkfilter (точнее 3 таких фильтра):
Code:
#define FILTERS 3

/*
./mkfilter -Bu -Lp -o 3 -a 0.0469 0.0000000000e+00 -l
*/

#define NZEROS 3
#define NPOLES 3
#define GAIN   4.1115485147e+02

double xv[FILTERS][NZEROS+1], yv[FILTERS][NPOLES+1];

static double filterstep(double v, int i)
{
        xv[i][0] = xv[i][1]; xv[i][1] = xv[i][2]; xv[i][2] = xv[i][3];
        xv[i][3] = v / GAIN;
        yv[i][0] = yv[i][1]; yv[i][1] = yv[i][2]; yv[i][2] = yv[i][3];
        yv[i][3] =   (xv[i][0] + xv[i][3]) + 3 * (xv[i][1] + xv[i][2])
                     + (  5.5347203431e-01 * yv[i][0]) + ( -1.9855726416e+00 * yv[i][1])
                     + (  2.4126432180e+00 * yv[i][2]);
        return yv[i][3];
}

Частота среза у этого фильтра составляет 0.0469 от частоты дискретизации, т.е. если вспомнить, что она у нас 28.63636 МГц, то частота среза будет 1.343045284 МГц (пока лучшие результаты именно с таким получаются - при большем значении в цветах появлятся черезпослосица, а при меньшем значении всё размыливается). Входной сигнал пропускается через первый фильтр (фильтр с индексом 0) для получения яркостной составляющей Y. Два других фильтра используются для фильтрации произведения входного сигнала на косинус и синус 3.5795 МГц сдвинутых на 200 градусов (причём из комадной строки можно ввести дополнительный сдвиг в градусах, если нужно) - в результате фильтры отделяют постоянную составляющую (разницу частот) от высокочастотной (суммы частот) выдавая цветоразностные составляющие V и U. Далее по формуле преобразования YUV в RGB для телевиденья стандартного разрешения (r=y+1.13983*v;g=y-0.39465*u-0.58060*v;b=y+2.03211*u) получаем цветовые составляющие R, G и B, искусственно ограничиенные снизу нулём, а сверху 255, которые заносятся в буфер экрана 1288x1008, сохранямый в 24-битном PNG формате в файле composite.png. Чтобы соотношение сторон было близко к 4:3 каждая строчка из входных 200 обрабатывается 5 раз (давая 1000 строк на выходе - возможно надо будет поддержать 16:9 тоже) и кроме того в картинке имеется 4 чёрных строки сверху и 4 чёрных строки снизу (для создания эффекта эдакой чёрной рамки) - всего 1008 строк. Горизонтальное разрешение 1288 обусловлено тем, что филтры дают задержку и первые 4-6 пикселов в каждой строке плавно выводят из черноты в картинку поэтому после обработанных 1280 пикселов (ширина видимого экрана NTSC при частоте дискретизации 28.63636 МГц) я прогоняю фильтры ещё 8 итераций, чтобы остатки изображения "пробежали" свою задержку и "проявились" до конца. Вот полноценный не ужатый вывод этой программы как есть:

Attachment:
composite.png
composite.png [ 335.28 KiB | Viewed 20162 times ]


Attachments:
cgatrick_xbm025.zip [12.26 KiB]
Downloaded 328 times

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973
16 Jan 2023 00:02
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Включив макрос COLORBARS можно заставить программу composite.c, приведённую выше, генерировать цветные полоски с цветами от 0 до 15:

Attachment:
composite-0.jpg
composite-0.jpg [ 49.77 KiB | Viewed 20149 times ]


Из комадной строки можно подвигать фазу - например сдвиг 90 градусов:

Attachment:
composite-1.jpg
composite-1.jpg [ 50.83 KiB | Viewed 20149 times ]


Сдвиг 180 градусов:

Attachment:
composite-2.jpg
composite-2.jpg [ 50.27 KiB | Viewed 20149 times ]


Сдвиг 270 градусов:

Attachment:
composite-3.jpg
composite-3.jpg [ 50.36 KiB | Viewed 20149 times ]


Как можно видеть эти цвета соответствуют палитрам Xorya с номерами 0, 1, 2 и 3:

Attachment:
composite-all4.jpg
composite-all4.jpg [ 21.27 KiB | Viewed 20149 times ]


Image

которые в свою очередь похожи на композитные палитры CGA (1), Tandy (2) и PCjr (3)...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


16 Jan 2023 00:26
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22782
Location: Silicon Valley
Reply with quote
Вспомнил, что забыл залить исходник на гитлаб :oops:

https://gitlab.com/shaos/xorlib/-/blob/master/tools/compositesim.c

(по сравнению с исходником выше добавилось комментов и изменилось название файла, чтобы не конфликтовать с composite из ImageMagick, который есть в любом линух-дистрибутиве)

P.S. Ну и ещё до кучи:
https://gitlab.com/shaos/xorlib/-/blob/master/examples/xbmdraw.c (вывод 200-строчных или 400-строчных XBM-файлов)
https://gitlab.com/shaos/xorlib/-/blob/master/examples/colodiag.c (апдейт диагонального теста двумя тонкими серыми линиями слева и справа)

P.P.S. Вот по диагональному тесту расписал где по краям получается эффективное разрешение 640 точек по ширине (только между чёрной и белой заливкой - отмечено зелёными стрелками), где 320 точек (отмечено жёлтыми стрелками и окружностями), а где остаётся 160 (цветное разрешение во всех остальных местах):

Attachment:
diags-edges.jpg
diags-edges.jpg [ 188.29 KiB | Viewed 18299 times ]


P.P.P.S. Дальнейшие эксперименты показали, что если гладкость есть при переходе из цвета в черноту (или белоту), то и обратный переход тоже будет "гладкий". Также переключение палитр никак не влияет на места гладкости - т.е. если нужно обеспечить гладкость перехода для какого-то другого цвета, надо просто подобрать нужную палитру, где переход с этого цвета станет "гладким" (хотя есть цвета, которые не будут гладко переходить в чёрное или белое в любой палитре). Теперь ещё надо поэкспериментировать с переходами из цвета в цвет...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


09 Dec 2023 13:09
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 32 posts ]  Go to page Previous  1, 2, 3  Next

Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.