Jump to content
IGNORED

Mad Pascal


Recommended Posts

Great, thanks for quick fix!

 

This unearthed another thing that seems to be semicolon handling bug, that took me long to replicate and identify the cause.

 

In attached code crucial part is in wpn.pas - legal no semicolon after CRT_Readkey prevents working of "targetHpPtr^ := 0;" (but only when assignment is to 0).

 

	if (targetHpPtr^ > g_baseIdx) then begin
		targetHpPtr^ := targetHpPtr^ - g_baseIdx;
		CRT_Write(' RESULT:'~);
		CRT_Write(targetHpPtr^);
		CRT_NewLine;
		CRT_Readkey // no semicilon here is legal but causes generation of incorrect code! only affects assignment of 0, other values would work correctly
		// adding semicolon generates correct code
	end else begin
		targetHpPtr^ := 0; // doesn't assign!
		CRT_Write(' EXPECTED 0:'~);
		CRT_Write(targetHpPtr^);
		CRT_NewLine;
	end;

 

Change can be seen in generated assembly code (in 2 places)

Bad code:

; optimize FAIL ('B_CRT.CRT_READKEY', WPN), line = 21

	jsr B_CRT.CRT_READKEY
	inx
	mva B_CRT.CRT_READKEY.RESULT :STACKORIGIN,x
	dex
	jmp l_0257
l_0239

; optimize OK (WPN), line = 24

	mwy TARGETHPPTR :bp2
	ldy #$00
	sta (:bp2),y

 

Wrong output:

INI HP:5 DMG:1 RESULT:4
INI HP:4 DMG:1 RESULT:3
INI HP:3 DMG:1 RESULT:2
INI HP:2 DMG:1 RESULT:1
INI HP:1 DMG:1 EXPECTED 0:1
INI HP:1 DMG:1 EXPECTED 0:1

 

After adding semicolon I got correct result:

INI HP:5 DMG:1 RESULT:4
INI HP:4 DMG:1 RESULT:3
INI HP:3 DMG:1 RESULT:2
INI HP:2 DMG:1 RESULT:1
INI HP:1 DMG:1 EXPECTED 0:0
INI HP:0 DMG:1 EXPECTED 0:0

And correct asm:

; optimize FAIL ('B_CRT.CRT_READKEY', WPN), line = 21

	jsr B_CRT.CRT_READKEY
	jmp l_0257
l_0239

; optimize OK (WPN), line = 24

	mwy TARGETHPPTR :bp2
	ldy #$00
	tya
	sta (:bp2),y

 

pascal_semicolon.zip

Link to comment
Share on other sites

8 hours ago, tebe said:

fixed

Thank you! Now works correctly also in my main project.

 

Now on my main project I stumbled on a "gotcha" that could be prevented with a warning, in attached program file dd.pas defines:

const COLOR_GREEN = 2;
const GREY = 1;

Which run.pas tries to simply print:

	writeln('COLOR_GREEN ', COLOR_GREEN);
	writeln('GREY ', GREY);

 

And the result is quite unexpected:

COLOR_GREEN 196
GREY 8

 

The base reason is that system.pas and ctr.pas define such generic-named constants and they take precedence (MP documentation warns about order of uses so it is somewhat OK).

 

This is easy to identify in such simple program, but in my main project MP didn't give me any warning and amazingly program worked differently on an earlied MP version - few weeks before -

it seems that in mad pascal updates since around 2024-02-01 something changed in resolving priority of such redefinitions,

this change may be perfectly OK and justified, but it would be a lot better if redefinition to a constant would be logged as a warning.

Also would be better if constants with simple names had some name prefix to prevent such clashes - seems that Bocianu's blibs to some extent follow such convention examples:

'PMG_gractl_missiles' in b_pmg.pas, 'CRT_screenWidth' in b_crt.pas

 

I understand that there may be no easy/backwards compatible solution to this.

pascal_redef.zip

Link to comment
Share on other sites

25 minutes ago, roeoender said:

 

Now on my main project I stumbled on a "gotcha" that could be prevented with a warning,

USES has recently been improved so that it works as in FPC

 

uses def_1, def_2;

def_2 is primary

 

uses def_2, def_1;

def_1 is primary

 

https://wiki.freepascal.org/Uses

Quote

However, two or more units listed in the uses clause might declare the same identifier. Then, only the identifier declared by the unit later in the list can be referred to using the short notation. Identifiers declared by earlier units in the uses clause can only be accessed via fully-qualified identifiers.

 

uses dd,crt;

begin
	writeln('COLOR_GREEN ', dd.COLOR_GREEN);
	writeln('GREY ', dd.GREY);
	readkey;
end.

 

Edited by tebe
  • Thanks 1
Link to comment
Share on other sites

50 minutes ago, tebe said:

USES has recently been improved so that it works as in FPC

 

uses def_1, def_2;

def_2 is primary

 

uses def_2, def_1;

def_1 is primary

 

https://wiki.freepascal.org/Uses

 

uses dd,crt;

begin
	writeln('COLOR_GREEN ', dd.COLOR_GREEN);
	writeln('GREY ', dd.GREY);
	readkey;
end.

 

Thank you for explaination.

Prefixing with unit name is a good solution.

Hope this info will be helpful to others.

Your MP and MADS are great tools!

  • Like 1
Link to comment
Share on other sites

Hi good afternoon.
I play with the madpascal and the plus4 (Yape)

What does the memory control/memory structure look like?

I would like to start the program at $8000 so that I can use the storage underneath myself.

how can I do that please?

Thanks.

Link to comment
Share on other sites

mp.exe hello.pas -t c4p -code:8000

 

Hello thanks for the information.

But I can't find the start address in hello.a65: 8000?

 

Thanks.

 

 

----------------------------------

; ------------------------------------------------------------
; Mad Pascal Compiler version 1.7.1 [2024/02/19] for 6502
; ------------------------------------------------------------

STACKWIDTH    = 16

TRUE        = 1
FALSE        = 0

; ------------------------------------------------------------

    org $02

zpage

.if .def(@AllocMem)||.def(MAIN.SYSTEM.GETMEM)||.def(MAIN.SYSTEM.FREEMEM)
psptr    .ds 2                        ; PROGRAMSTACK Pointer
.fi

bp    .ds 2
bp2    .ds 2

eax    .ds 4                        ;8 bytes (aex + edx) -> divREAL
edx    .ds 4
ecx    .ds 4

TMP
ztmp
ztmp8    .ds 1
ztmp9    .ds 1
ztmp10    .ds 1
ztmp11    .ds 1

STACKORIGIN    .ds STACKWIDTH*4
zpend

; ------------------------------------------------------------

ax    = eax
al    = eax
ah    = eax+1

cx    = ecx
cl    = ecx
ch    = ecx+1

dx    = edx
dl    = edx
dh    = edx+1

    org eax

FP1MAN0    .ds 1
FP1MAN1    .ds 1
FP1MAN2    .ds 1
FP1MAN3    .ds 1

    org ztmp8

FP1SGN    .ds 1
FP1EXP    .ds 1

    org edx

FP2MAN0    .ds 1
FP2MAN1    .ds 1
FP2MAN2    .ds 1
FP2MAN3    .ds 1

    org ztmp10

FP2SGN    .ds 1
FP2EXP    .ds 1

    org ecx

FPMAN0    .ds 1
FPMAN1    .ds 1
FPMAN2    .ds 1
FPMAN3    .ds 1

    org bp2

FPSGN    .ds 1
FPEXP    .ds 1

; ------------------------------------------------------------
    opt h-f+
    org $1001
    org [a($1001)],$1001
    basic_start(START)

    org $100E

CODEORIGIN

    STATICDATA

; ------------------------------------------------------------

RTLIB
    icl 'rtl6502_c4p.asm'

.print 'ZPAGE: ',zpage,'..',zpend-1

.print 'RTBUF: ',@buf,'..',@buf+255

.print 'RTLIB: ',RTLIB,'..',*-1

; ------------------------------------------------------------

START
    tsx
    stx MAIN.@halt+1

VLEN    = VARDATASIZE-VARINITSIZE
VADR    = DATAORIGIN+VARINITSIZE

    ift (VLEN > 0) && (VLEN <= 256)
    ldx #256-VLEN
    lda #$00
    sta:rne VADR+VLEN-256,x+
    eli VLEN>256
    m@init
    eif

.ifdef psptr
    mwa #PROGRAMSTACK psptr
.fi

    lda #$0e
    jsr $ffd2                    ; shifted charset

    ldx #$00
    stx bp                        ; BP = 0

    dex                        ; X = 255

    UNITINITIALIZATION

.local    MAIN                        ; PROCEDURE

    jmp l_0012

; ------------------------------------------------------------

.local    SYSTEM                        ; UNIT

; ------------------------------------------------------------

M_PI_2    = $0648
D_PI_2    = $0192
D_PI_180    = $04
FMOPENREAD    = $04
FMOPENWRITE    = $08
FMOPENAPPEND    = $09
FMOPENREADWRITE    = $0C
SCREENWIDTH    = DATAORIGIN+$0000
SCREENHEIGHT    = DATAORIGIN+$0002
DATESEPARATOR    = DATAORIGIN+$0004
FILEMODE    = DATAORIGIN+$0005
GRAPHMODE    = DATAORIGIN+$0006
IORESULT    = DATAORIGIN+$0007
EOLN    = DATAORIGIN+$0008
RNDSEED    = DATAORIGIN+$0009

.endl                            ; UNIT SYSTEM

; ------------------------------------------------------------

.local    CRT                        ; UNIT

; ------------------------------------------------------------

BW40    = $00
CO40    = $01
BW80    = $02
CO80    = $03
MONO    = $07
C40    = $01
C80    = $03
BLACK    = $00
WHITE    = $01
RED    = $02
CYAN    = $03
PURPLE    = $04
GREEN    = $05
BLUE    = $06
YELLOW    = $07
ORANGE    = $08
BROWN    = $09
YELLOW_GREEN    = $0A
PINK    = $0B
BLUE_GREEN    = $0C
LIGHT_BLUE    = $0D
DARK_BLUE    = $0E
LIGHT_GREEN    = $0F
BLINK    = $80

.endl                            ; UNIT CRT
l_0012

; optimize FAIL ('@print', hello.pas), line = 5

    @printSTRING #CODEORIGIN+$0000
    @printEOL
@exit

@halt    ldx #$00
    txs

    rts

; ------------------------------------------------------------

; ------------------------------------------------------------

.local    @DEFINES
C4P
.endl

.local    @RESOURCE
.endl

.endl                            ; MAIN

; ------------------------------------------------------------
; ------------------------------------------------------------

.macro    UNITINITIALIZATION

    .ifdef MAIN.SYSTEM.@UnitInit
    jsr MAIN.SYSTEM.@UnitInit
    .fi

    .ifdef MAIN.CRT.@UnitInit
    jsr MAIN.CRT.@UnitInit
    .fi
.endm

; ------------------------------------------------------------

    ift .SIZEOF(MAIN.SYSTEM) > 0
    .print 'SYSTEM: ',MAIN.SYSTEM,'..',MAIN.SYSTEM+.SIZEOF(MAIN.SYSTEM)-1
    eif

    ift .SIZEOF(MAIN.CRT) > 0
    .print 'CRT: ',MAIN.CRT,'..',MAIN.CRT+.SIZEOF(MAIN.CRT)-1
    eif

.nowarn    .print 'CODE: ',CODEORIGIN,'..',MAIN.@RESOURCE-1

; ------------------------------------------------------------

    ?adr = *
    ift (?adr < ?old_adr) && (?old_adr - ?adr < $120)
    ?adr = ?old_adr
    eif

    org ?adr
    ?old_adr = *

DATAORIGIN
.by  $28 $00 $18 $00 $2D $0C

VARINITSIZE    = *-DATAORIGIN
VARDATASIZE    = 11

PROGRAMSTACK    = DATAORIGIN+VARDATASIZE

    .print 'DATA: ',DATAORIGIN,'..',PROGRAMSTACK

; ------------------------------------------------------------

.macro    STATICDATA
.by  $0D $48 $65 $6C $6C $6F $20 $57  $6F $72 $6C $64 $20 $21
.endm

    end

-------------------------------------------------------

Link to comment
Share on other sites

Hi, Thank You.
At 75 years old, I can no longer remember things that are more than 2 weeks old, that's why I ask so many questions.

 

I have another problem with starting a program life.pas for the X16 under Windows 11.

 

This is my request in the madpascal folder:
mp.exe -t x16 c:\madpascal\samples\x16\CRT\life.pas
 

but there is a message saying that it was entered incorrectly.

 

Thanks.
greeting

fehler.jpg

Edited by neuling
Link to comment
Share on other sites

this is my fork. It is unfinished and probably never will be.

in order to use new target you need to compile mp.pas to mp.exe. Those in the repo are old ones and are not recompiled.

 

fpc -MDelphi -vh -O3 mp.pas

Edited by MADRAFi
Link to comment
Share on other sites

@tebe,

 

I am not sure, but I think I've just found a problem with memory alignment for variables with fixed address (set by absolute) which are types of records containing arrays. Please see the following source code:

 

program Test;

const
  SIZE = 3;

type
  TStructure = record
    array_of_bytes: array[0..SIZE - 1] of Byte;
    array_of_words: array[0..SIZE - 1] of Word;
    byte_field: Byte;
  end;

var
  auto: TStructure;
  fixed: TStructure absolute $4000;

begin
end.

 

There are two variables of the same type - auto, which address is automatically set by compiler and fixed with address set by hand.

When I look on lst file I can see that alignemnt for members of auto variable is proper but for fixed not. Please see the following excerpt from lst file.

 

   262 = 205F			adr.AUTO	= DATAORIGIN+$000B	; [10] RECORD
   263 2032			.var AUTO	= adr.AUTO .word
   264 = 205F			adr.AUTO.ARRAY_OF_BYTES	= [DATAORIGIN+$000B] .array [3]
   265 2032			.var AUTO.ARRAY_OF_BYTES	= adr.AUTO.ARRAY_OF_BYTES .word
   266 = 2062			adr.AUTO.ARRAY_OF_WORDS	= [DATAORIGIN+$000E] .array [3] .word
   267 2032			.var AUTO.ARRAY_OF_WORDS	= adr.AUTO.ARRAY_OF_WORDS .word
   268 = 2068			AUTO.BYTE_FIELD	= DATAORIGIN+$0014
   269 = 4000			adr.FIXED	= $4000
   270 2032			.var FIXED	= adr.FIXED .word
   271 = 4000			adr.FIXED.ARRAY_OF_BYTES	= $4000
   272 2032			.var FIXED.ARRAY_OF_BYTES	= adr.FIXED.ARRAY_OF_BYTES .word
   273 = 4002			adr.FIXED.ARRAY_OF_WORDS	= $4002
   274 2032			.var FIXED.ARRAY_OF_WORDS	= adr.FIXED.ARRAY_OF_WORDS .word
   275 = 4004			FIXED.BYTE_FIELD	= $4004

 

You can see that the local offsets of members are proper in case of auto variable:
- array_of_bytes: 0=$205F-$205F
- array_of_words: 3=$2062-$205F
- byte_field: 9=$2068-$205F
 
But local offsets of members are invalid for fixed variable:
- array_of_bytes: 0=$4000-$4000
- array_of_words: 2=$4002-$4000
- byte_field: 4=$4004-$4000
 
I am using the latest version of MadPascal and MadAssembler taken from github. Have you ever found the problem?
I really need to use records with fixed addresses for cartridge version of Time Wizard. Could you please fix it?
 
Thank you in advance for your help. :)
Link to comment
Share on other sites

  • 5 weeks later...

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...