Jump to content
IGNORED

Mad Pascal


Recommended Posts

For purist - pure Mad Pascal tested with SpartaDOS on emulator.

 

(*
* This is a part of Quatari 256B intro
* <https://demozoo.org/productions/280623>
*)
program Landscape;

uses crt, graph;

var
  cursor_y : byte absolute $e0;
  prev_y   : byte absolute $e1;
  color    : byte absolute $e2;
  x        : byte absolute $e3;
  y        : byte absolute $e4;
  rnd      : byte absolute $d20a;

  color_height: array[0..13] of byte = (
    170,150,144,144,122,122,110,110,94,94,86,86,82,80
  );

begin
  InitGraph(9);  
  SetBKColor($b0);
  
  for x := 79 downto 0 do begin
    prev_y := 1;
    for color := 13 downto 0 do begin
      SetColor(color);
      cursor_y := color_height[color];
      if rnd < $80 then dec(color_height[color]);
      if rnd < $80 then inc(color_height[color]);
      for y := prev_y to cursor_y do PutPixel(x,y);
      prev_y := cursor_y;
    end;
  end;  

  ReadKey;
end.

 

LANDO.COM landscape2.pas

Link to comment
Share on other sites

Can someone please explain what I'm doing wrong here?

 

I'm trying to reproduce the simple rainbow effect but in pascal.

 

Here's my code:

 

program Rainbow;
uses atari;

var
	i: byte;
	sdmctl_2: word = $22f;
begin
	poke(sdmctl, 0);
	poke(sdmctl_2, 0);
	poke($22f, 0);

//	while true do
//	begin
//		i := peek(vcount);
//		poke(colpf4, i);
//	end;

	asm {
		lda #0
		sta atari.sdmctl
		
loop	lda vcount
		sta colpf4
		jmp loop
	};
end.

I'm trying to do the equivalent of "lda #0; sta $22f" using a poke.

However, the first 2 examples don't work.

 

1. poke(sdmctl,0); is producing:

   201 203F A9 00			lda #$00
   202 2041 85 8F			sta bp+1
   203 2043 AC 2F 02			ldy ATARI.SDMCTL
   204 2046 A9 00			lda #$00
   205 2048 91 8E			sta (bp),y

I'm getting the SDMCTL address from the atari module, which is defined as "sdmctl: byte absolute $22F;"

I'm guessing that's for reading the value out of the address, as it's defined as a byte absolute?

 

2. poke(sdmctl_2, 0); is producing:

   209 204A AD E1 20			lda SDMCTL_2+1
   210 204D 85 8F			sta bp+1
   211 204F AC E0 20			ldy SDMCTL_2
   212 2052 A9 00			lda #$00
   213 2054 91 8E			sta (bp),y

which is doing something I can't explain.

 

3. poke($22f,0);

only the 3rd version is producing the code I expect

 

   217 2056 A9 00			lda #$00
   218 2058 8D 2F 02			sta $022F

 

My question therefore is:

a) how do I use values in the Atari module to do the equivalent of what I want?

b) Why didn't my definition of sdmctl_2 work as it's just "$22f"? FIXED: I needed to use const, not var.
c) Do I need to duplicate vars as consts like this?

 

Once I understand this part, I might be able to work out why my while loop isn't working either, where I'm trying to reproduce "lda vcount; sta colpf4; jmp loop" in a pascal while loop. Fixed: again, needed to use const instead of var.

 

 

Thanks!

Edited by fenrock
Found some answers to my questions.
Link to comment
Share on other sites

18 minutes ago, fenrock said:

ok, I just learned the difference between const and var, so have fixed the sdmctl_2 and while loop problems.

 

The question is still open as to how to use the atari module values like "var sdmctl: byte absolute $22F;" in a poke statement?

No need to poke.

SDMCTL := value;

will store the value into the location $22F

Link to comment
Share on other sites

17 minutes ago, fenrock said:

ok, I just learned the difference between const and var, so have fixed the sdmctl_2 and while loop problems.

 

The question is still open as to how to use the atari module values like "var sdmctl: byte absolute $22F;" in a poke statement?

If you use absolute in variable declaration no need to use POKE because variable is mapped to specific address.

Link to comment
Share on other sites

aha, thanks both.

Getting close to perfect with:

 

	sdmctl := 0;

	repeat colpf4 := vcount;
	until false;

It's flickering because of the code implementing the repeat/until false;

Is there a more efficient way to do that? Or is it assembly only to shortcut this type of thing?

 

This works, but feels unsatisfactory:

 

begin
	sdmctl := 0;
asm {
	loop:
};
		colpf4 := vcount;
asm {
	jmp loop
};

Although MADS pascal says it supports "goto", i couldn't get it working :(

Edited by fenrock
Link to comment
Share on other sites

15 minutes ago, fenrock said:

aha, thanks both.

Getting close to perfect with:

 


	sdmctl := 0;

	repeat colpf4 := vcount;
	until false;

It's flickering because of the code implementing the repeat/until false;

Is there a more efficient way to do that? Or is it assembly only to shortcut this type of thing?

 

This works, but feels unsatisfactory:

 


begin
	sdmctl := 0;
asm {
	loop:
};
		colpf4 := vcount;
asm {
	jmp loop
};

 

Not sure what you are trying to achive?

It is looping very quickly through the color palette of the Atari, hence the flickering.

If you want some sort of gradient effect (i.e. many colors at once), you need to work with DLIs, etc.

 

In any way, Mad Pascal is perfectly capable of providing the required execution speed.

Link to comment
Share on other sites

var
  antic_wsync  : byte absolute $D40A; // wait for horizontal synchronization
  antic_vcount : byte absolute $D40B; // vertical line counter
  gtia_colpf2  : byte absolute $D018;

begin
  repeat
    gtia_colpf2 := antic_vcount;
    antic_wsync := 1;
  until false;
end.

atari000.png.3988e6ba195132d9da67970e96a14f5b.png

Edited by zbyti
tab to spaces
  • Like 1
Link to comment
Share on other sites

2 minutes ago, starfighter said:

Not sure what you are trying to achive?

It is looping very quickly through the color palette of the Atari, hence the flickering.

If you want some sort of gradient effect (i.e. many colors at once), you need to work with DLIs, etc.

 

In any way, Mad Pascal is perfectly capable of providing the required execution speed.

I'm trying to (re)learn pascal and how it works on the atari and comparing it to assembly examples I have.

I'm not trying to have a go in any way at the performance of mp, it's superb, just trying to translate from one to another, and learn anything along the way.

 

... and I see that 

5 minutes ago, zbyti said:

var
  antic_wsync  : byte absolute $D40A; // wait for horizontal synchronization
  antic_vcount : byte absolute $D40B; // vertical line counter
  gtia_colpf2  : byte absolute $D018;

begin
  repeat
    gtia_colpf2 := antic_vcount;
    antic_wsync := 1;
  until false;
end.

 

has just shown me how to remove the flicker I was seeing by using wsync.

 

thankyou both!

 

Link to comment
Share on other sites

4 minutes ago, fenrock said:

I'm trying to (re)learn pascal and how it works on the atari and comparing it to assembly examples I have.

I'm not trying to have a go in any way at the performance of mp, it's superb, just trying to translate from one to another, and learn anything along the way.

 

... and I see that 

has just shown me how to remove the flicker I was seeing by using wsync.

 

thankyou both!

 

 

Ah okay, cool, I am on the same route, although I do not have much assembly background.

I think Mad Pascal is the best high level language plus the speed which is very close to pure assembly.

 

Regarding the rainbow colors:

It always amazes me how easy you can put colors on the screen on the Atari! Such a great and flexible design!

 

Link to comment
Share on other sites

20 hours ago, fenrock said:

My question therefore is:

a) how do I use values in the Atari module to do the equivalent of what I want?

b) Why didn't my definition of sdmctl_2 work as it's just "$22f"? FIXED: I needed to use const, not var.
c) Do I need to duplicate vars as consts like this?

 

Once I understand this part, I might be able to work out why my while loop isn't working either, where I'm trying to reproduce "lda vcount; sta colpf4; jmp loop" in a pascal while loop. Fixed: again, needed to use const instead of var.

uses atari;

begin
  repeat
    colpf2 := vcount;
    wsync := vcount;
  until false;
end.

 

Edited by zbyti
tabs to spaces
Link to comment
Share on other sites

I was trying to understand GR 9 - here are the result:

(*
* this is a part of quatari 256b intro
* <https://demozoo.org/productions/280623>
*)
program LandscapeSlideshow;

uses atari, crt;

const
  lms = $8010;
  dl8: array [0..201] of byte = (
    $70,$70,$70,
    $4f,lo(lms),hi(lms),
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,
    $4f,0,hi(lms)+$10,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
    $0f,
    $41,lo(word(@dl8)),hi(word(@dl8))
  );
  base: array[0..13] of byte = (
    170,150,144,144,122,122,110,110,94,94,86,86,82,80
  );

var
  stop     : byte absolute $e0;
  start    : byte absolute $e1;
  c        : byte absolute $e2;
  x        : byte absolute $e3;
  i        : byte absolute $e4;
  p        : pbyte absolute $e5;
  rnd      : byte absolute $d20a;

  colheight: array[0..13] of byte;

begin
  sdlstl := word(@dl8);
  gprior := $40;
  color4 := $b0;

  repeat
    sdmctl := 0; pause(10);
    move(@base, @colheight, 14);
    //fillchar(pointer(lms), $2000, 0);
    for x := 39 downto 0 do begin
      for i := 1 downto 0 do begin
        p := pointer(lms + x); start := 0;
        for c := 13 downto 0 do begin
          stop := colheight[c];
          if start > stop then begin
            dec(p,(start - stop) * 40);
            stop := start;
            start := colheight[c];
          end;
          while start < stop do begin
            if i = 1 then
              p^ := c
              //p[0] := (p[0] and %11110000) or c
            else
              p^ := (p^ and %00001111) or (c shl 4);
            inc(p,40);
            inc(start);
          end;
          start := stop;
          if boolean(rnd and 1) then dec(colheight[c]);
          if boolean(rnd and 1) then inc(colheight[c]);
        end;
      end;
    end;
    pause; sdmctl := $22;
    pause(150);
  until keypressed;
  textmode(0);
end.

 

slideshow.pas slideshow.xex new-slideshow.xex new-slideshow.pas

Edited by zbyti
refactored listing - no flickering
Link to comment
Share on other sites

  • 3 weeks later...

Hello Tebe,

 

would is be possible to combine mp.exe and mads.exe into a single .exe?

Like is it the case with gcc, there you you have 2 phases but you can control everything with a single class.

Parameter for mads could be passed via a separate "-..." parameter.

 

This would simplify the usage and make it easier to integrate it into an IDE/build.

Also you'll always have "the right" MADS version implicitly.

 

Still all intermediate fiels etc. shall be created of course.

 

Best regards, Peter.

  • Like 1
Link to comment
Share on other sites

@fenrock your flames ;) Action! slow approach.

 

(*
* Fire by koalka/bbsl/karzelki
*)

program Fire;

const
  screen  = $6400;
  charset = $6000;
  dl: array [0..25] of byte = (
    $4f,lo(screen),hi(screen),
    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    $41,lo(word(@dl)),hi(word(@dl))
  );

var
  b0i    : byte absolute $e0;
  b1i    : byte absolute $e1;
  tmp    : byte absolute $e2;
  sdmctl : byte absolute $22f;
  gprior : byte absolute $26f;
  color4 : byte absolute $2c8;
  chbas  : byte absolute $2f4;
  colbk  : byte absolute $d01a;
  random : byte absolute $d20a;
  sdlstl : word absolute $230;
  matrix : array [0..0] of byte;

begin
  color4 := $20; tmp := 0; 
  sdlstl := word(@dl); chbas := hi(charset);
  gprior := $40; sdmctl := $21;

  matrix := pointer(charset);
  for b0i := 0 to $10 do begin
    for b1i := 0 to 7 do matrix[b1i + b0i * 8] := tmp;
    inc(tmp,$11);
  end;

  FillChar(pointer(screen), $400, 0);

  matrix := pointer(screen-1);
  while true do begin
    for b0i := 0 to 255 do begin
      tmp := matrix[b0i];
      inc(tmp,matrix[b0i+1]);
      inc(tmp,matrix[b0i + 2]);
      inc(tmp,matrix[b0i + $21]);
      tmp := tmp shr 2;
      matrix[b0i-30] := tmp;

      tmp := matrix[b0i + $100];
      inc(tmp,matrix[b0i + $101]);
      inc(tmp,matrix[b0i + $102]);
      inc(tmp,matrix[b0i + $121]);
      tmp := tmp shr 2;
      matrix[b0i + $e2] := tmp;

      tmp := matrix[b0i + $200];
      inc(tmp,matrix[b0i + $201]);
      inc(tmp,matrix[b0i + $202]);
      inc(tmp,matrix[b0i + $221]);
      tmp := tmp shr 2;
      matrix[b0i + $1e2] := tmp;
    end;
    //colbk := 10; pause;
    for b0i := $1f downto 0 do matrix[$2e1 + b0i] := random and 15;
  end;
end.

 

fire.pas fire.xex

Edited by zbyti
FillChar
  • Like 1
Link to comment
Share on other sites

(*
* Fire by koalka/bbsl/karzelki
*)

program Fire;

uses atari;

const
  screen  = $6400;
  charset = $6000;
  dl: array [0..25] of byte = (
    $4f,lo(screen),hi(screen),
    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    $41,lo(word(@dl)),hi(word(@dl))
  );

var
  b0i    : byte absolute $e0;
  b1i    : byte absolute $e1;
  tmp    : byte absolute $e2;

  p0: PByte absolute $e3;
  p1: PByte absolute $e5;
  p2: PByte absolute $e7;

  matrix : array [0..0] of byte;

begin
  color4 := $20; tmp := 0;
  sdlstl := word(@dl); chbas := hi(charset);
  gprior := $40; sdmctl := $21;

  matrix := pointer(charset);
  for b0i := 0 to $10 do begin
    for b1i := 0 to 7 do matrix[b1i + b0i * 8] := tmp;
    inc(tmp,$11);
  end;

  FillChar(pointer(screen), 4 * $ff, 0);

 while true do begin

    p0:=pointer(screen-1);
    p1:=pointer(screen-1+7*32);
    p2:=pointer(screen-1+15*32);

    for b0i := 0 to 255 do begin

      tmp := p0[32];
      inc(tmp,p0[32+1]);
      inc(tmp,p0[32+2]);
      inc(tmp,p0[64+1]);
      tmp := tmp shr 2;
      p0[2] := tmp;

      tmp := p1[32];
      inc(tmp,p1[32+1]);
      inc(tmp,p1[32+2]);
      inc(tmp,p1[64+1]);
      tmp := tmp shr 2;
      p1[2] := tmp;

      tmp := p2[32];
      inc(tmp,p2[32+1]);
      inc(tmp,p2[32+2]);
      inc(tmp,p2[64+1]);
      tmp := tmp shr 2;
      p2[2] := tmp;

      inc(p0);
      inc(p1);
      inc(p2);
    end;

    //colbk := 10; pause;

    p0:=pointer(screen-1+23*32);

    for b0i := $1f downto 0 do p0[b0i] := rnd and 15;
  end;
end.

 

fire.obx fire.pas

Edited by tebe
  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...