Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 18 июн 2025, 17:11

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 14 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Drawing some bytes to the screen
СообщениеДобавлено: 24 июн 2013, 20:52 
Не в сети

Сообщения: 104
I put a new function in basic
drawchar

Цитата:
void Basic_drawchar(SHORTINT gfx,SHORTINT x,SHORTINT y)
{
__asm
#ifdef __SDCC
PUSH IX
LD IX,#0
ADD IX,SP
#endif
LD D,4(IX)
LD B,5(IX)
LD C,6(IX)


LD HL,#16384
LD A,B
ADD A,L
LD L,A

LD A,C
CP #8
JP NC,secondthird$
RRC A
RRC A
RRC A
OR L
LD L,A

JP drawing$

secondthird$:
CP #16
JP NC,thirdthird$
LD A,#8
ADD A,H
LD H,A

LD A,C
SUB #8
RRC A
RRC A
RRC A
OR L
LD L,A

JP drawing$

thirdthird$:
LD A,#16
ADD A,H
LD H,A
LD A,C
SUB #16
RRC A
RRC A
RRC A
OR L
LD L,A


drawing$:
LD A,D
CP #1
JP NZ,dontdraw$
LD A,#255
LD (HL),A
INC H
LD (HL),#129
INC H
LD (HL),#129
INC H
LD (HL),#129
INC H
LD (HL),#129
INC H
LD (HL),#129
INC H
LD (HL),#129
INC H
LD (HL),#255

dontdraw$:
LD A,4(IX)
CP #2
JP NZ,dontdraw2$

dontdraw2$:

#ifdef __SDCC
POP IX
#endif
__endasm;

}


check out the attachment to see it in action

Im putting the bytes of the graphic inside the drawing function but I want to make function accept a pointer to some graphics, how would I do that?
Could I put some numbers(bytes) into an oberon array and pass the pointer to the array to asm?

Also it seems that SHORTINT is signed -127 to 128
I need an unsigned byte but SHORTCARD isn't accepted by ofront


Вложения:
hi.tap [15.55 КБ]
Скачиваний: 1125
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 25 июн 2013, 04:28 
Не в сети

Сообщения: 104
ok I looked at printstring to figure out how to do it

Цитата:
void Basic_drawchar_func(SHORTINT *gfx, SHORTINT x,SHORTINT y)
{
__asm
#ifdef __SDCC
PUSH IX
LD IX,#0
ADD IX,SP
#endif
LD E,4(IX)
LD D,5(IX)
LD B,6(IX)
LD C,7(IX)


LD HL,#16384
LD A,B
ADD A,L
LD L,A

LD A,C
CP #8
JP NC,secondthird$

JP drawing$

secondthird$:
CP #16
JP NC,thirdthird$
LD A,#8
ADD A,H
LD H,A
LD A,C
SUB #8

JP drawing$

thirdthird$:
LD A,#16
ADD A,H
LD H,A
LD A,C
SUB #16

drawing$:
RRC A
RRC A
RRC A
OR L
LD L,A


LD (HL),#255

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

INC H
INC DE
LD A,(DE)
ADD #128
LD (HL),A

#ifdef __SDCC
POP IX
#endif
__endasm;

}


I have to find out how to turn a signed byte into unsigned now

EDIT- ohh put ADD #128 to every byte


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 25 июн 2013, 11:58 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Yeah, very good!

slenkar писал(а):
Could I put some numbers(bytes) into an oberon array and pass the pointer to the array to asm?
General question: how to specify a data (sprites, fonts, tiles, levels, music etc) in an Oberon program? That is a problem, therefore Oberon has not constant arrays (like Turbo Pascal or C). Maybe we'll fix this problem in future.

Then now you can specify data in a non-constant array:
Код: "OBERON"
  1. PROCEDURE DrawChar (x, y: SHORTINT; VAR gfx: SYSTEM.BYTE);
  2.  
  3. ...
  4.  
  5. (* User level code: *)
  6. VAR
  7. char: ARRAY 8 OF SYSTEM.BYTE;
  8. BEGIN
  9. char[0] := 0FFX; char[1] := 081X; char[2] := 081X; char[3] := 081X;
  10. char[4] := 081X; char[5] := 081X; char[6] := 081X; char[7] := 0FFX;
  11. DrawChar(10, 10, char); (* Probably it works *)
You can without problem to have your own Rsrc module, and specify all resources as C arrays. How to do it - see example ZXDev/Lib/Rsrc.c

The same way I've used in the game Dash. See:

Oberon interface:
https://github.com/Oleg-N-Cher/Dash/blob/master/Src/ZxSpec%20(Ofront-SDCC)/Mod/Rsrc.odc
C implementation:
https://github.com/Oleg-N-Cher/Dash/blob/master/Src/ZxSpec%20(Ofront-SDCC)/Rsrc.c

I recommend you do not call the procedure "drawchar". Why? Because your drawchar will be draw not only chars, and rather, the tiles - small squares that make up a graphic. For ZX it's good to have size 8x8 pixels (or 16x16). With color, or without. I propose to start a new library GrTiles. At first, it may contain such interface:
Код: "OBERON"
  1. DEFINITION GrTiles;
  2.  
  3. TYPE
  4. Tile* = INTEGER; (* OR SYSTEM.CARDINAL, no matter, but size = 2 bytes *)
  5. Coords* = SHORTINT;
  6.  
  7. PROCEDURE DrawTile* (x, y: Coords; tile: Tile); (* Draw a color tile 8x8 pixels. *)
  8. PROCEDURE GetTileByNum* (num: SHORTINT): Tile; (* Get a tile address by its number. *)
  9. (* SHORTINT will be enough for <=127 tiles *)
  10.  
  11. END GrTiles.

slenkar писал(а):
Also it seems that SHORTINT is signed -127 to 128
I need an unsigned byte but SHORTCARD isn't accepted by ofront
To add this feature, you need to rebuild Ofront for Linux with this changes (see the commit) and use SYSTEM.SHORTCARD, SYSTEM.CARDINAL, SYSTEM.LONGCARD. But it's a very basic support of unsigned types (may be problems), we must improve it.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 25 июн 2013, 12:09 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
I want to suggest another way to define a data in Oberon program. See this code:

And another question: can a Basic loader be written in Oberon? Yes, it's even relocatable! And may be placed in a Basic line after REM:
Код: "OBERON"
  1. MODULE BasicLoader;
  2. IMPORT SYSTEM, Basic;
  3. CONST
  4. Color = 51H;
  5. VAR
  6. title, attr: SYSTEM.CARDINAL; count, bit: SHORTINT; byte: SET;
  7. BEGIN
  8. Basic.DEFDATAREL(title, 96 - 12 - 6);
  9. Basic.DATA12(0FH,000H,018H,002H,1FH,0C0H,030H,004H,21H,0C0H,020H,004H);
  10. Basic.DATA12(0CH,0E0H,020H,004H,0CH,0E0H,078H,0CDH,18H,0C9H,07DH,0EDH);
  11. Basic.DATA12(18H,0D9H,04DH,02EH,19H,0D3H,04DH,06CH,31H,096H,04DH,06EH);
  12. Basic.DATA12(33H,0BEH,0D9H,0EFH,33H,03EH,0F1H,0ADH,26H,006H,0C0H,000H);
  13. Basic.DATA12(0CH,00CH,080H,000H,78H,00DH,080H,000H,00H,019H,080H,000H);
  14. Basic.DATA12(06H,071H,080H,000H,03H,0E3H,000H,000H,00H,003H,000H,000H);
  15. Basic.DATA6 (00H,007H,000H,000H,00H,00EH);
  16. attr := 22624;
  17. FOR count := 96 - 12 - 6 TO 1 BY -1 DO
  18. byte := SYSTEM.VAL(SET, Basic.READ(title));
  19. FOR bit := 7 TO 0 BY -1 DO
  20. IF bit IN byte THEN Basic.POKE(attr, Color) END; INC(attr);
  21. END;
  22. END;
  23. Basic.PAUSE(Basic.WaitAKey); (* To see the fullscreen. *)
  24. END BasicLoader.
First parameter of DEFDATAREL is a variable that has resulting address of data. Second parameter is data size.

P.S. Procedures DEFDATAREL, DATA*, READ was added today, re-download the Basic library.


Вложения:
Комментарий к файлу: Basic Loader in Oberon
BasicLoader.tap [378 байт]
Скачиваний: 1143
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 25 июн 2013, 18:57 
Не в сети

Сообщения: 104
there are a couple of things I dont understand about that example

where does 96-12-6 come from?

Does basic loader mean loading screen?

Can I use decimal instead of hex?


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 25 июн 2013, 21:49 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
slenkar писал(а):
where does 96-12-6 come from?
It's data size, specified after DEFDATAREL. Constant (calculable) expression that is:

768 bytes (ZX's screen attributes)
DIV 8
= 96 bytes (all of attribute bytes are packed into bits)
- 12 (upper blank attribute lines on screen)
- 6 (lower blank attribute lines on screen)

slenkar писал(а):
Does basic loader mean loading screen?
It's just a part of the loader's functions. It has packed attribute screen, and unpack/show it. Except this, it will be load a code block from tape/TR-DOS disk (the last feature isn't implemented yet).

slenkar писал(а):
Can I use decimal instead of hex?
Sure. Use a decimal value every time where hex may be written. And if you need to specify a character by a decimal code, use CHR(DecCharCode).

P.S. If you want to know more about how to work with bits in Oberon, there is article "Wirth N. SET: A neglected data type, and its compilation for the ARM".


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 26 июн 2013, 02:29 
Не в сети

Сообщения: 104
I read about SET in 3 different Oberon manuals and I still dont understand them :oops: :lol:

why is MAX(SET) on spectrum 31?
That would mean it uses 6 bits?

If I knew why 31 it would help me understand


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 26 июн 2013, 12:41 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
slenkar писал(а):
I read about SET in 3 different Oberon manuals and I still dont understand them :oops: :lol:
In fact, Oberon's SET is machine-independent and maximally right way to work with bits. :) But I must confess I don't understand something about SETs too. :D

slenkar писал(а):
why is MAX(SET) on spectrum 31?
Why 31? I've launched:
Код: "OBERON"
  1. Basic.PRINT(MAX(SET));
And it shows 7. This means that used 8 bits numbered 0 to 7:

7 6 5 4 3 2 1 0

If you want to use all bits set, just write:
Код: "OBERON"
  1. set := {0, 1, 2, 3, 4, 5, 6, 7}; (* Full set. *)
If all bits reset, write:
Код: "OBERON"
  1. set := {}; (* Empty set. *)
To check bit in byte, use:
Код: "OBERON"
  1. IF 3 IN set THEN ... (* It checks is the third bit = 1. *)
  2. (* In C, it looks: if (set & 8) ... /* dec 8 is bin 1000, which corresponds to the third bit. */ *)

Btw, I've used MAX(SET) = 7 only for ZX. So it is made for more efficiency. In Oberon (and in WinDev) it is really 31 - that corresponds to 0 to 31 bits = 4 bytes. And you can set this value for your own project in the Ofront configurator - the file Obj/Ofront.par:

type size(bytes) alignment
SET 1 1

As Oberon is a strongly typed language, it does not encourage work with bits as numbers and with numbers as bits. I think it's very good decision, because it encourages more accurate to formalize problems, but it does not encourage a quick and dirty coding. Therefore many C programmers do not like Oberon (and Modula-2 too). :D


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 27 июн 2013, 23:28 
Не в сети

Сообщения: 104
thanks I think I get it now

let me know if this sounds good


Код: "OBERON"
  1. DEFINITION GrTiles;
  2.  
  3. TYPE
  4. Tile* = INTEGER; (* OR SYSTEM.CARDINAL, no matter, but size = 2 bytes *)
  5. Coords* = SHORTINT;
  6. BackgroundColor=INTEGER;
  7.  
  8. PROCEDURE DrawTile* (x, y: Coords; tile: Tile); (* Draw a color tile 8x8 pixels. *)
  9. PROCEDURE GetTileByNum* (num: SHORTINT): Tile; (* Get a tile address by its number. *)
  10. (* SHORTINT will be enough for <=127 tiles *)
  11. PROCEDURE ClearTile* (INTEGER x;INTEGER y);(*simply paints pixels over the tile in BackgroundColor*)
  12. PROCEDURE GetTile* (INTEGER x;INTEGER y):Array of SHORTINT;(* grabs tile info from screen to be able to make a sprite move across a tile and replace the tile*)
  13. PROCEDURE DrawGottenTile* (INTEGER x;INTEGER y:Array of SHORTINT;)(* draws grabbed tile info back to screen*)
  14. END GrTiles.


we need gettile to make sure other sprites that are not moving dont get deleted from the screen

For DOS:
If you look at turbo C it has a BGIDEMO, I think we only need putpixel and getpixel


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Drawing some bytes to the screen
СообщениеДобавлено: 28 июн 2013, 15:36 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
I've planned to place tile graphic and pixel graphic to different modules, it's a way to have unified look to graphic at all, and possible independent from a platform. You can to start implementation of that interface proposed by you, and look what I've done today. :)

Код: "OBERON"
  1. DEFINITION GrTiles;
  2.  
  3. CONST (** Colors - skipped. *)
  4.  
  5. TYPE
  6. Colors = INTEGER;
  7. Coords = INTEGER;
  8. Tile = INTEGER;
  9.  
  10. PROCEDURE DrawMonoTile (x: INTEGER; y: INTEGER; tile: INTEGER);
  11. PROCEDURE DrawMonoTile8x8 (x: INTEGER; y: INTEGER; tile: INTEGER);
  12. PROCEDURE DrawTile (x: INTEGER; y: INTEGER; tile: INTEGER);
  13. PROCEDURE DrawTile8x8 (x: INTEGER; y: INTEGER; tile: INTEGER);
  14. PROCEDURE SetColors (attr: INTEGER);
  15.  
  16. END GrTiles.
Why such interface? I'll try to answer this question...

I have tried to unify the view of the tiles as a whole, and try to design platform-independent tiles that will be a good as for Spectrum, as for other platforms (DOS, Windows, Linux (SDL)).

DrawTile8x8 needs to be able to specify tile size, and to have (in future) a possibility to draw tiles with different size (DrawTile16x16, DrawTile8x16, DrawTile16x8, etc).

DrawTile needs to be able to work with tiles without specifying their size (it's good for crossplatform development). For example, you will have under ZX the tile size 8x8 (two-colors), and under MS-DOS - 10x10 (colored). But a game's main logic module may be the same.

SetColors and DrawMonoTile need to be able to draw monochrome (or rather even two-colors) tiles, with a possibility to specify this colors (attributes). This is a traditional look for old good classical graphics libraries - background and foreground (or paper and ink). This mono tiles may be conveniently used for drawing characters, frames, pseudo graphic, etc. Because in old school for such things are often of use of little colors, and I like this approach even for modern platforms. In addition, we can then add a drawing with logical operations (and, or, xor), transparency, etc.

So you can see what I made today in this direction.
Код: "OBERON"
  1. MODULE DemoTiles;
  2. IMPORT Til := GrTiles, B := Basic;
  3.  
  4. VAR
  5. i: SHORTINT; square: Til.Tile;
  6. BEGIN (*$MAIN*)
  7. B.Init; B.BORDER(B.Red);
  8. B.DEFDATAREL(square, 8 + 1);
  9. (*Pixels:*) B.DATA8(0FFH, 81H, 81H, 81H, 81H, 81H, 81H, 0FFH);
  10. (*Attrib:*) B.DATA1(Til.BlueOnOlive);
  11. FOR i := 0 TO 23 DO Til.DrawTile(i, i, square) END;
  12. FOR i := 24 TO 31 DO Til.DrawTile(i, 23, square) END;
  13. Til.SetColors(Til.WhiteOnBlack);
  14. FOR i := 8 TO 23 DO Til.DrawMonoTile(i, 1, square) END;
  15. Til.SetColors(Til.CyanOnBlue);
  16. FOR i := 10 TO 21 DO Til.DrawMonoTile(i, 3, square) END;
  17. Til.SetColors(Til.BlackOnWhite);
  18. FOR i := 12 TO 19 DO Til.DrawMonoTile(i, 5, square) END;
  19. Til.SetColors(Til.GreenOnMagenta);
  20. FOR i := 14 TO 17 DO Til.DrawMonoTile(i, 7, square) END;
  21. B.PAUSE(B.WaitAKey);
  22. B.Quit;
  23. END DemoTiles.
All your suggestions are welcome. But I have an important question for you. Do you prefer to tile drawing routines to be named "DrawTile" or "PutTile"?


Вложения:
DemoTiles.png
DemoTiles.png [ 1.1 КБ | Просмотров: 25630 ]
DemoTiles.tap [648 байт]
Скачиваний: 1437
Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 14 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club