tebe6502 / mad-pascal Goto Github PK
View Code? Open in Web Editor NEWMad Pascal Compiler for 6502 (Atari XE/XL, C64, C4Plus, Neo6502)
Mad Pascal Compiler for 6502 (Atari XE/XL, C64, C4Plus, Neo6502)
// spodziewany wynik to 3! i taki podaje Free Pascal
uses crt;
const
size = 2; // od zera to size+1 elementow
var
board : array [0..size] of byte;
i : byte;
counter : word = 0;
procedure generate(n: byte);
var
i, tmp: byte;
begin
if n = 0 then
begin
//for tmp in board do write(tmp); writeln;
inc(counter);
end
else
begin
for i := 0 to n do begin
tmp := board[i]; board[i] := board[n]; board[n] := tmp;
generate(n-1);
tmp := board[i]; board[i] := board[n]; board[n] := tmp;
end;
end;
end;
begin
for i := 0 to size do board[i] := i;
generate(size);
writeln('liczba permutacji: ', counter);
repeat until keypressed;
end.
Cześć.
Dostaję taki błąd podczas asemblacji:
stereogr.a65 (4210) ERROR: Undeclared label IDIVAX_CL (BANK=0)
Fragment stereogr.a65:
`
; optimize OK (stereogr.pas), line = 425
lda Y
sta :ax
lda Y+1
sta :ax+1
lda #$08
sta :cx
jsr idivAX_CL
lda :eax
sta BY
Linia 425 w pascalu:
BY := Y div 8;
Pełna funkcja (zagnieżdżona, nested):
function GetBoardLevel(X, Y: Word): Byte;
var
BX, BY: Byte;
begin
if (X >= 40) and (X < 280) then
begin
BX := (X - 40) div 10;
BY := Y div 8; // <- linia 425
Result := Board[BX, BY];
end
else
Result := 0;
end;
`
uses crt;
var
itout : word;
itin : word;
index : word;
primes : array[0..1027] of word;
begin
index := 0;
primes[0] := 2; primes[1] := 3; inc(index, 2);
for itout := 5 to 8191 do begin
if (itout and 1) <> 0 then begin
for itin := 3 to itout-1 do begin
if (itout mod itin) = 0 then break;
end;
if itin = (itout-1) then begin
write(itout, ',');
primes[index] := itout; inc(index);
end;
end;
end;
writeln('ok');
end.
fpc test.pas
Free Pascal Compiler version 3.0.4+dfsg-18ubuntu2 [2018/08/29] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling test.pas
test.pas(7,3) Note: Local variable "primes" is assigned but never used
Linking test
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?
25 lines compiled, 0.2 sec
1 note(s) issued
Projects/FreePascal$ ./test
5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,1
51,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,3
07,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,4
63,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,6
43,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,8
27,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013
,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,11
63,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,
1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,148
3,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1
621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789
,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,19
87,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,
2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,230
9,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2
467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663
,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,28
01,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,
2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,318
7,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3
359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533
,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,36
97,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,
3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,405
1,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4
241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423
,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,46
21,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,
4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,498
7,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5
171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387
,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,55
31,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,
5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,588
1,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6
113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287
,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,64
73,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,
6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,686
3,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7
039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243
,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,74
87,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,
7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,784
1,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8
059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,ok
Projects/FreePascal$ mp-build-a8 test.pas r
Mad Pascal Compiler version 1.6.5 [2021/01/03] for 6502
Compiling test.pas
test.pas (17) Warning: Variable 'ITIN' does not seem to be initialized
27 lines compiled, 0.71 sec, 6145 tokens, 560 idents, 189 blocks, 6 types
1 warning(s) issued
ZPAGE: $0080..$00D7
RTLIB: $2004..$215B
SYSTEM: $2199..$219C
CODE: $2000..$22E1
DATA: $22E4..$2B00
Writing listing file...
Writing object file...
7497 lines of source assembled in 6 pass
758 bytes written to the object file
I's not possible to dereference a pointer to a record. See (1)
in the code below.
It works in FPC.
uses crt;
type
TRecord = record x, y: Byte end;
var
r: TRecord;
p: ^TRecord;
procedure PrintRecord(var r1: TRecord);
begin
WriteLn(r1.x, ' ', r1.y);
end;
begin
r.x := 2;
r.y := 3;
p := @r;
WriteLn(Word(@r));
PrintRecord(r);
WriteLn;
WriteLn(Word(p));
PrintRecord(p^); // (1)
ReadKey();
end.
OS: Ubuntu 20.04.3 x86_64
FPC 3.2.2
Output:
44880
2 3
44880
2 3
Mad-Pascal Compiler version cca6b6f
Output:
Compiling ./test3.pas
./test3.pas (24,17) Error: Syntax error, '.' expected but ')' found
uses crt;
function sum_algo(n: byte): integer;
begin
result := (n * (n + 1)) shr 1;
end;
//---------------------------------------------
function sum(n: byte): integer;
begin
if n = 1 then result := 1
else result := n + sum(n - 1);
end;
//---------------------------------------------
function tail_call(n: byte; i: integer): integer;
begin
if n = 0 then result := i
else result := tail_call(n - 1, i + n);
end;
function tail_sum(n: byte): integer;
begin
result := tail_call(n,0);
end;
//---------------------------------------------
// big n crash the system ;)
begin
writeln(sum(10));
writeln(sum_algo(10));
writeln(tail_sum(20));
writeln(sum_algo(20));
repeat until keypressed;
end.
Recursion can go beyond Mad Pascal's software stack. I strongly recommend provide info about this possibility due to small software stack or maybe you can try to implement tail recursion optimization.
uses crt;
const
freq_ratio = 4;
var
freq:float;
fdiv:byte;
tpq:longint;
qtm:longint;
begin
qtm:=454545;
tpq:=120;
freq:=1/((qtm/1000000)/tpq)*freq_ratio;
fdiv:=round(64000/freq);
writeLn(fdiv);
end.
The above code will cause the computer to hang. This is because a variable named fdiv
is used, which conflicts with a math procedure of the same name.
An initialized variable of a pointer to a record (like (1)
in the code below) has value 0
regardless of actual initial value.
uses crt;
type
TRecord = record x, y: Byte end;
var
a: array [0..1] of Byte = (2, 3);
p: ^TRecord = @a; // (1)
begin
// p := @a; // (2)
WriteLn(Word(@a));
WriteLn(a[0], ' ', a[1]);
WriteLn;
WriteLn(Word(p));
WriteLn(p^.x, ' ', p^.y);
ReadKey();
end.
(1)
- initialized pointer variable which doesn't work
(2)
- a workaround
OS: Ubuntu 20.04.3 x86_64
FPC 3.2.2
Output for both cases of (2)
:
59424
2 3
59424
2 3
Mad-Pascal Compiler version cca6b6f
Output when (2)
commented:
8597
2 3
0
0 0
Output when (2)
uncommented:
8597
2 3
8597
2 3
var seed1, seed2, seed3 : byte;
function pseudo_rnd_dir(): byte;
var
tmp : word;
begin
Inc(seed2);
tmp := seed2 + seed2 + seed1;
seed1 := lo(tmp);
seed2 := (seed1 xor seed2) + hi(tmp);
seed3 := seed2 - seed3;
pseudo_rnd_dir := seed3 and 3;
end;
not correct result in the loop
function pseudo_rnd_dir(): byte;
var
tmp : word;
begin
Inc(seed2);
tmp := word(seed2 + seed2 + seed1);
seed1 := lo(tmp);
seed2 := (seed1 xor seed2) + hi(tmp);
seed3 := seed2 - seed3;
pseudo_rnd_dir := seed3 and 3;
end;
don't fix the issue ;)
function pseudo_rnd_dir(): byte;
var
tmp : word;
begin
Inc(seed2); tmp := 0;
tmp := seed2 + seed2 + seed1;
seed1 := lo(tmp);
seed2 := (seed1 xor seed2) + hi(tmp);
seed3 := seed2 - seed3;
pseudo_rnd_dir := seed3 and 3;
end;
works in the loop :]
I have a suggestion for a new modifier for procedures/functions. MACRO.
Its purpose would be to insert the whole code of the procedure/function at the place of procedure or function call.
The idea is to force the compiler not to use the JMP/JSR instruction.
In case of designing fast recursive calls, it would cost the code size, but (I hope) it would speed up the code execution, e.g. in loops.
Mam taką sytuację z plikiem zasobów recource.rc
SFX_DATA_ADDR rcasm 'data.asm';
SFX_ORG rcasm 'mole.asm';
Pierwszy z nich data.asm
zawiera definicje danych wraz z przypisanymi doń odpowiednimi etykietami, np:
(fragment pliku data.asm)
data_sfx_0 ; KEY CLEAN LONG
.by $7C $A6 $00 $A5 $00 $A4 $01 $A3 $00 $A3 $00 $A3 $3F $A3 $00 $A3
.by $00 $A3 $83 $00
; address: $C014 (offset: $0014)
data_sfx_1 ; KEY CLEAN ECHO
.by $7C $A6 $00 $A5 $00 $A4 $00 $A3 $00 $A2 $00 $A1 $80 $00
Drugi mole.asm
, też zawiera definicje danych, ale korzysta z etykiet z pierwszego pliku.
(fragment pliku mole.asm)
; org $7126 ; ----------------------------------------
; current block address: 7126
sfxptr
dta a(data_sfx_0) ; offset in data 0000 optimized 1=>0
dta a(data_sfx_1) ; offset in data 0014 optimized 2=>1
Jak sprawić, by taka sytuacja zadziałała? Czy to jest w ogóle możliwe, by w jednym pliku zasobów wykorzystać etykiety z drugiego pliku? Jeśli jest to wykonalne, to byłbym ogromnie wdzięczny za, wytłumaczenie, jak należy się odwołać w drugim pliku do etykiet z pierwszego. Dziękuję
Z tego co widzę w pliku A65
(po kompilacji MP) jest w nim taka klauzula:
.local RESOURCE
icl 'atari\resource.asm'
?EXTDETECT = 0
?VBXDETECT = 0
RCASM 'song/data.asm' SFX_API.SFX_DATA_ADDR 0 0 0 0 0 0 0 0
RCASM 'song/mole.asm' SFX_API.SFX_ORG 0 0 0 0 0 0 0 0
.endl
Rozumiem, że zasoby RCASM
będą kompilowane w przestrzeni nazw RESOURCE
.
Czy poszczególne zasoby (linie RCASM
) dostają jeszcze jakąś własną przestrzeń nazw?
this works:
procedure initFonts;
var fonts: array [0..(8 * 6 - 1)] of byte = (
24,24,36,36,36,60,102,90, // ship up
0,3,62,197,197,62,3,0, // ship left
0,192,124,163,163,124,192,0, // ship right
90,102,60,36,36,36,24,24, // ship down
0,60,110,98,70,118,60,0, // obstacle 1
0,60,118,70,98,110,60,0 // obstacle 2
);
begin
Move(pointer($d000), pointer($6000), $400);
Move(fonts, pointer($6000 + (8 * $50)), 8 * 6);
// set bit 2
RAMROMSEL := RAMROMSEL and %11111011;
// 24 = $6000 / $400 on 2-7 bits
CHBAS := (CHBAS and %11) or 24 shl 2;
end;
and this don't:
const fonts: array [0..(8 * 6 - 1)] of byte = (
24,24,36,36,36,60,102,90, // ship up
0,3,62,197,197,62,3,0, // ship left
0,192,124,163,163,124,192,0, // ship right
90,102,60,36,36,36,24,24, // ship down
0,60,110,98,70,118,60,0, // obstacle 1
0,60,118,70,98,110,60,0 // obstacle 2
);
procedure initFonts;
begin
Move(pointer($d000), pointer($6000), $400);
Move(fonts, pointer($6000 + (8 * $50)), 8 * 6);
// set bit 2
RAMROMSEL := RAMROMSEL and %11111011;
// 24 = $6000 / $400 on 2-7 bits
CHBAS := (CHBAS and %11) or 24 shl 2;
end;
https://github.com/tebe6502/Mad-Pascal/blob/master/samples/c4plus/siege/inc/init.inc
I have a suggestion for the modifier name, to change it to "RELEASELOCAL" or "FREELOCALVAR" or something that clearly associates with the modifier's function of allocating/releasing memory for local variables.
It will be useful with (for example):
https://github.com/mnaberez/py65
https://github.com/docmarionum1/py65emu
this 82090de broke my suite code https://github.com/zbyti/a8-mad-pascal-bench-suite
ldy #CONTEXT.ALIGN-DATAORIGIN
suite.a65 (1588) ERROR: Value out of range (-324 must be between 0 and 255)
ldy #CONTEXT.STATE-DATAORIGIN
suite.a65 (1597) ERROR: Value out of range (-318 must be between 0 and 255)
ldy #CONTEXT.STATE-DATAORIGIN+$04
suite.a65 (1612) ERROR: Value out of range (-314 must be between 0 and 255)
ldy #CONTEXT.STATE-DATAORIGIN+$08
suite.a65 (1627) ERROR: Value out of range (-310 must be between 0 and 255)
ldy #CONTEXT.STATE-DATAORIGIN+$0C
suite.a65 (1642) ERROR: Value out of range (-306 must be between 0 and 255)
ldy #CONTEXT.LEN-DATAORIGIN
suite.a65 (1657) ERROR: Value out of range (-320 must be between 0 and 255)
ldy #CONTEXT.BUFCNT-DATAORIGIN
suite.a65 (1665) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (1699) ERROR: Value out of range (-318 must be between 0 and 255)
suite.a65 (1714) ERROR: Value out of range (-314 must be between 0 and 255)
suite.a65 (1729) ERROR: Value out of range (-310 must be between 0 and 255)
suite.a65 (1744) ERROR: Value out of range (-306 must be between 0 and 255)
ldy #CONTEXT.STATE-DATAORIGIN+$00
suite.a65 (2110) ERROR: Value out of range (-318 must be between 0 and 255)
suite.a65 (2129) ERROR: Value out of range (-314 must be between 0 and 255)
suite.a65 (2148) ERROR: Value out of range (-310 must be between 0 and 255)
suite.a65 (2167) ERROR: Value out of range (-306 must be between 0 and 255)
suite.a65 (2186) ERROR: Value out of range (-320 must be between 0 and 255)
suite.a65 (2243) ERROR: Value out of range (-324 must be between 0 and 255)
suite.a65 (2265) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2273) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2303) ERROR: Value out of range (-322 must be between 0 and 255)
add #CONTEXT.BUFFER-DATAORIGIN
suite.a65 (2312) ERROR: Value out of range (-302 must be between 0 and 255)
suite.a65 (2332) ERROR: Value out of range (-322 must be between 0 and 255)
ldy #CONTEXT.BUFCNT-DATAORIGIN+$01
suite.a65 (2352) ERROR: Value out of range (-321 must be between 0 and 255)
suite.a65 (2366) ERROR: Value out of range (-302 must be between 0 and 255)
suite.a65 (2382) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2451) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2462) ERROR: Value out of range (-302 must be between 0 and 255)
suite.a65 (2516) ERROR: Value out of range (-320 must be between 0 and 255)
suite.a65 (2522) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2550) ERROR: Value out of range (-321 must be between 0 and 255)
suite.a65 (2562) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2576) ERROR: Value out of range (-322 must be between 0 and 255)
suite.a65 (2648) ERROR: Value out of range (-318 must be between 0 and 255)
add #CONTEXT.STATE-DATAORIGIN
suite.a65 (2663) ERROR: Value out of range (-318 must be between 0 and 255)
suite.a65 (2686) ERROR: Value out of range (-314 must be between 0 and 255)
suite.a65 (2701) ERROR: Value out of range (-318 must be between 0 and 255)
suite.a65 (2724) ERROR: Value out of range (-310 must be between 0 and 255)
suite.a65 (2739) ERROR: Value out of range (-318 must be between 0 and 255)
suite.a65 (2762) ERROR: Value out of range (-306 must be between 0 and 255)
suite.a65 (2777) ERROR: Value out of range (-318 must be between 0 and 255)
bne @+
suite.a65 (4418) ERROR: Branch out of range by $0085 bytes
suite.a65 (4629) ERROR: Branch out of range by $0085 bytes
bcc @+
suite.a65 (4633) ERROR: Branch out of range by $0086 bytes
suite.a65 (4643) ERROR: Branch out of range by $0087 bytes
beq l_0DEA
suite.a65 (4645) ERROR: Branch out of range by $0088 bytes
suite.a65 (4870) ERROR: Branch out of range by $0085 bytes
suite.a65 (4897) ERROR: Branch out of range by $0091 bytes
suite.a65 (4901) ERROR: Branch out of range by $0086 bytes
suite.a65 (5144) ERROR: Branch out of range by $0085 bytes
suite.a65 (5168) ERROR: Branch out of range by $0085 bytes
suite.a65 (5315) ERROR: Branch out of range by $008B bytes
suite.a65 (5319) ERROR: Branch out of range by $0080 bytes
suite.a65 (6538) ERROR: Branch out of range by $008E bytes
suite.a65 (6542) ERROR: Branch out of range by $0083 bytes
Setting the loading of resources that are close to each other (within the page) causes their mutual (probably) deletion.
e.g.
res1 = $b500;
res2 = $b520;
res3 = $b5f0;
res1 rcasm 'res1.asm'
res2 rcasm 'res2.asm'
res3 rcasm 'res3.asm'
Resource sizes tiny (several bytes). The compilation goes without any problems, but running it gives an error.
I have to manipulate the loading order, between other resources located in other memory areas, e.g.
-First I load 'res1',
I would need something like this (below) construction for the code working in ROM for example on cartridge:
function foo(a, b, c: byte): byte absolute $f0; register;
begin
RESULT := 0
end;
Other then first field of a record is incorrectly passed as a variable to a procedure.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version 6882126
Mad-Assembler version 40bfd80
uses crt;
type
Point = record x, y: Byte end;
Segment = record a, b: Point end;
var s: Segment;
procedure PrintPoint(var p: Point);
begin
WriteLn(p.x, ' ', p.y);
end;
procedure PrintSegment(var s: Segment);
begin
PrintPoint(s.a);
PrintPoint(s.b);
end;
begin
s.a.x := 1;
s.a.y := 2;
s.b.x := 3;
s.b.y := 4;
PrintSegment(s);
ReadKey();
end.
1 2
3 4
1 2
1 2
mp-build sieve.pas
Mad Pascal Compiler version 1.6.4 [2020/05/03] for 6502
Compiling sieve.pas
An unhandled exception occurred at $000000000044444F:
EAccessViolation: Access violation
$000000000044444F
ZPAGE: $0080..$00DA
RTLIB: $2000..$2058
; -------------
sieve.a65 (471) ERROR: Missing .ENDL
STATICDATA
sieve.a65 (90) ERROR: Undeclared macro STATICDATA (BANK=0)
stx MAIN.@Halt+1
sieve.a65 (105) ERROR: Undeclared label MAIN.@Halt (BANK=0)
VLEN = VARDATASIZE-VARINITSIZE
sieve.a65 (111) ERROR: Undeclared label VARDATASIZE (BANK=0)
VADR = DATAORIGIN+VARINITSIZE
sieve.a65 (112) ERROR: Undeclared label DATAORIGIN (BANK=0)
ift VADR > $BFFF
sieve.a65 (114) ERROR: The referenced label VADR has not previously been defined properly
eli (VLEN>0) && (VLEN<=256)
sieve.a65 (116) ERROR: The referenced label VLEN has not previously been defined properly
eli VLEN>0
sieve.a65 (120) ERROR: The referenced label VLEN has not previously been defined properly
mwa #PROGRAMSTACK psptr
sieve.a65 (124) ERROR: Undeclared label PROGRAMSTACK (BANK=0)
mva $340,x MAIN.IOCB@COPY,x-
sieve.a65 (127) ERROR: Undeclared label MAIN.IOCB@COPY (BANK=0)
UNITINITIALIZATION
sieve.a65 (138) ERROR: Undeclared macro UNITINITIALIZATION (BANK=0)
jmp l_0034
sieve.a65 (142) ERROR: Undeclared label L_0034 (BANK=0)
SCREENWIDTH = DATAORIGIN+$0000
sieve.a65 (243) ERROR: Undeclared label DATAORIGIN (BANK=0)
SCREENHEIGHT = DATAORIGIN+$0002
sieve.a65 (244) ERROR: Undeclared label DATAORIGIN (BANK=0)
DATESEPARATOR = DATAORIGIN+$0004
sieve.a65 (245) ERROR: Undeclared label DATAORIGIN (BANK=0)
FILEMODE = DATAORIGIN+$0005
sieve.a65 (251) ERROR: Undeclared label DATAORIGIN (BANK=0)
GRAPHMODE = DATAORIGIN+$0006
sieve.a65 (252) ERROR: Undeclared label DATAORIGIN (BANK=0)
IORESULT = DATAORIGIN+$0007
sieve.a65 (253) ERROR: Undeclared label DATAORIGIN (BANK=0)
EOLN = DATAORIGIN+$0008
sieve.a65 (254) ERROR: Undeclared label DATAORIGIN (BANK=0)
RNDSEED = DATAORIGIN+$0009
sieve.a65 (255) ERROR: Undeclared label DATAORIGIN (BANK=0)
sta Result
sieve.a65 (367) ERROR: The referenced label RESULT has not previously been defined properly
mva RESULT :STACKORIGIN,x
sieve.a65 (379) ERROR: The referenced label RESULT has not previously been defined properly
RESULT = DATAORIGIN+$000C
sieve.a65 (391) ERROR: Undeclared label DATAORIGIN (BANK=0)
@VarData = RESULT
sieve.a65 (393) ERROR: The referenced label RESULT has not previously been defined properly
TEXTATTR = DATAORIGIN+$000B
sieve.a65 (401) ERROR: Undeclared label DATAORIGIN (BANK=0)
mva :rtclok+2 Result
sieve.a65 (464) ERROR: Undeclared label RESULT (BANK=0)
mva :rtclok+1 Result+1
sieve.a65 (465) ERROR: Undeclared label RESULT (BANK=0)
mva :rtclok Result+2
sieve.a65 (466) ERROR: Undeclared label RESULT (BANK=0)
mva #$00 Result+3
sieve.a65 (467) ERROR: Undeclared label RESULT (BANK=0)
Writing listing file...
MADS ma flagę -o
która pozwala wskazać miejsce docelowe dla pliku binarnego.
Mad Pascal też ma flagę -o
ale oznacza ona optymalizację.
Potrzebował bym w Mad Pascalu również możliwości wskazania docelowego miejsca dla np. foo.a65
. Najlepiej jakby te flagi uzyskały spójność znaczeniową i -o
w MP przerodziło się np. -opt
a -o
zaczęło oznaczać output
.
If the "-target: raw" compiler switch is used, the "-code:" directive is ignored. The fixed address $1000 is used to start the program instead of the one specified in the "-code:" switch.
Przydało by się np.:
procedure openmode(m : byte); assembler;
asm
lda m
jsr $ef9c
end;
móc zrobić tak wygodnie jak w Action!:
PROC OPENMODE=$EF9C(BYTE M)
czy Millfork:
asm void openmode(byte register(a) m) @ $ef9c extern
Przykład:
program testobj;
type
TFoo = object
X,Y: Byte;
P: Word;
procedure Test;
end;
procedure TFoo.Test;
begin
//WriteLn(P);
if P < 4 then
WriteLn('Wrong');
WriteLn(P);
end;
var
R: TFoo;
begin
R.P := 1023;
R.Test;
ReadLn;
end.
Co ciekawe, jeśli wykonamy Writeln(P) przed porównaniem, to wynik porównania wydaje się być poprawny.
I got an error related to the detection of an infinite loop, for ( probably) a FillChar routine with the length parameter set to 1024 bytes.
Since I was clearing PMG memory, I could afford to delete one less byte (1023) and that caused the error to not show up.
However, in the course of expanding the program, something changed. The point is that I restored the amount of memory being filled, back to 1024 and the error is not there.
This is strange to me.
Writing a value to a two-dimensional Float16 array does not work correctly.
When You use Single or Byte instead of Float16 in the same code then it produces expected results.
Mad-Pascal Compiler version 3bd174c
Mad-Assembler version 40bfd8045e7ae28174c5f074ea7f96d59fd1f248
uses crt;
var
t: array [0..1, 0..2] of Float16;
procedure Add(x, y: Float16);
var k: SmallInt = 0;
begin
t[k,0] := x;
t[k,1] := y;
t[k,2] := t[k,0] + t[k,1];
end;
procedure Print;
begin
WriteLn(t[0,0], ' ', t[0,1], ' ', t[0,2]);
end;
begin
Add(1, 2);
Print;
ReadKey();
end.
1.000000 2.000000 3.000000
1.000000 2.001953 0.000000
An attempt to cast a pointer on the left side of an assignment causes compilation error.
A workaround is to use a local variable with proper type but it consumes memory.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version 9cc0813
Mad-Assembler version 40bfd80
uses crt;
type
Box = record x: Byte end;
BoxPtr = ^Box;
var data: array [0 .. 1] of Byte;
procedure DoSomething(p: Pointer);
begin
BoxPtr(p)^.x := BoxPtr(p)^.x + 1;
end;
begin
data[0] := 10; data[1] := 20;
DoSomething(@data);
WriteLn(data[0], ' ', data[1]);
ReadKey();
end.
11 20
test.pas (11,6) Error: Variable identifier expected
An attempt to pass fields of a record as variables to a procedure for a record given by a pointer yields compilation error of .a65 file.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version d7619c5
Mad-Assembler version 40bfd80
See also #90
uses crt;
type
Point = record x, y: Byte end;
Segment = record a, b: Point end;
SegmentPtr = ^Segment;
var s: Segment;
procedure PrintPoint(var p: Point);
begin
WriteLn(p.x, ' ', p.y);
end;
procedure PrintSegment(sp: SegmentPtr);
begin
PrintPoint(sp^.a);
PrintPoint(sp^.b);
end;
begin
s.a.x := 1; s.a.y := 2;
s.b.x := 3; s.b.y := 4;
PrintSegment(@s);
ReadKey();
end.
1 2
3 4
mva :STACKORIGIN,x
test10.a65 (462) ERROR: Unexpected end of line
mp main.lpr
Mad Pascal Compiler version 1.6.6 [2021/11/02] for 6502
Error: Can't open file 'main.pas'
Wygodnie by było jakby Mad Pascal nie narzekał na rozszerzenie używane przez Lazarus IDE.
When you uncoment Pause in line 13 program prints 16 (correct).
With a commented out pause, the program writes out 11, which is wrong.
uses crt;
var
l,c,d:byte;
dest: array[0..50] of char;
begin
l := 11;
c:=1;
d:=1;
repeat
Inc(d,4);
Inc(c,3);
until c > l;
//pause;
l := d - 1;
dest[0] := char(l);
writeln(byte(dest[0]));
readkey
end.
The use of fields of a record dereferrenced from a pointer passed to a procedure cause the code to compile but the MADS is not able to produce a binary.
uses crt;
type
TRecord = record x, y: Byte end;
TRecordPtr = ^TRecord;
var
r: TRecord;
p: ^TRecord;
procedure PrintRecord(p1: TRecordPtr);
begin
WriteLn(p1^.x, ' ', p1^.y);
end;
begin
r.x := 2;
r.y := 3;
p := @r;
WriteLn(Word(@r));
PrintRecord(@r);
WriteLn;
WriteLn(Word(p));
PrintRecord(p);
ReadKey();
end.
OS: Ubuntu 20.04.3 x86_64
FPC 3.2.2
Output:
44880
2 3
44880
2 3
Mad-Pascal Compiler version cca6b6f
Mad-Assembler version ecb0c7e11b61a1fc4d36d10a9fb21ef83280cf02
Output:
mva (:bp2),y adr.P1,y-
test4.a65 (421) ERROR: Undeclared label ADR.P1 (BANK=0)
mwa #adr.P1 P1
test4.a65 (422) ERROR: Undeclared label ADR.P1 (BANK=0)
An index variable is not incremented without calling some procedure first (line (1)
in sample code).
When line (1)
is uncommented then it works as expected.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version ece71f6
Mad-Assembler version 40bfd80
uses crt;
var t: array [0..1] of Byte;
procedure DoSomething(k: Byte);
var x1, x2: Byte;
begin
x1 := t[k];
// WriteLn(''); // (1)
k := k + 1;
x2 := t[k];
WriteLn(x1, ' ', x2);
end;
begin
t[0] := 1;
t[1] := 3;
DoSomething(0);
ReadKey();
end.
1 3
1 1
My target platform is a C256 Foenix retro computer which uses a 65816. I'd like to use my own assembler rather than Mad-Assembler but have noticed the heavy use of built-in macros. Is there a macro definition library available? or is there a way to disable the use of the built-in macros?
Arithmetic on a pointer passed by variable modifies the data it refers to while it should effect the pointer itself.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version 9cc0813
Mad-Assembler version 40bfd80
uses crt;
type BytePtr = ^Byte;
var
data: array [0 .. 1] of Byte;
p: BytePtr;
procedure DoSomething(var p2: Pointer);
begin
p2 := p2 + 1;
end;
begin
data[0] := 10; data[1] := 20;
p := @data;
Write(p^);
DoSomething(p);
WriteLn(' ', p^);
ReadKey();
end.
10 20
10 11
Poniższy kod działa, ale dla case trzeba zostawić globalną zmienną typu record dla case - czyli kod nie spełnia swojej funkcji.
procedure playerMove(p: pointer);
var
ply : ^Player;
begin
ply := p;
checkAvailDir(ply.x, ply.y);
if availDir = 0 then begin
playerDie := true;
putChar(ply.x, ply.y, PLY_CRASH, PLY1_COLOUR + $80);
end else begin
t0n := false;
repeat
t0b := 1 shl Random(4);
if (availDir and t0b) <> 0 then t0n := true;
until t0n;
ply.dir := Direction(t0b);
putChar(ply.x, ply.y, PLY_TAIL, PLY1_COLOUR);
case player1.dir of
up : Dec(ply.y);
down : Inc(ply.y);
left : Dec(ply.x);
right : Inc(ply.x);
end;
putChar(ply.x, ply.y, PLY_HEAD, PLY1_COLOUR);
end;
end;
Gdy kluczowe miejsce zmienię na:
case ply.dir of
up : Dec(ply.y);
down : Inc(ply.y);
left : Dec(ply.x);
right : Inc(ply.x);
end;
otrzymuję komunikat od kompilatora:
Error: Incompatible types: got "ENUM" expected "BYTE"
Gdy próbuję posłużyć się zmienną d typu wyliczeniowego:
d := ply.dir;
case d of
up : Dec(ply.y);
down : Inc(ply.y);
left : Dec(ply.x);
right : Inc(ply.x);
end;
to program się kompiluje ale player się nie porusza, więc nie spełniony jest żaden z warunków case.
Short and to the point:
The following code does not execute correctly:
var
screen:array[0..239] of byte absolute BUFFER_ADDR;
i:byte;
begin
for i:=0 to 9 do
begin
if (condition) then
begin
(* something if true *)
end
else
begin
screen[ofs]:=ch; ofs:=ofs+20;
screen[ofs]:=ch;
end;
end;
end;
The following, works fine:
var
screen:array[0..239] of byte absolute BUFFER_ADDR;
i:byte;
begin
for i:=0 to 9 do
begin
if (condition) then
begin
(* something if true *)
end
else
begin
screen[ofs]:=ch;
screen[ofs+20]:=ch;
end;
end;
end;
I think I have conveyed all that is needed to analyze this case.
From time to time I get a message during compilation:
start.a65 (126) WARNING: Infinite loop by label VADR
.
.
.
17107 lines of source assembled in 20 pass (infinite loop)
start.a65 warning code:
; ------------------------------------------------------------
START
tsx
stx MAIN.@halt+1
.ifdef fmulinit
fmulinit
eif
VLEN = VARDATASIZE-VARINITSIZE
VADR = DATAORIGIN+VARINITSIZE <-- Here he points out the warning.
ift VADR > $BFFF
ert 'Invalid memory address range ',VADR
eli (VLEN>0) && (VLEN<=256)
ldx #256-VLEN
lda #0
sta:rne VADR+VLEN-256,x+
eli VLEN>0
@fill #VADR #VLEN #0
eif
Trying to run a program compiled this way, ends up with the emulator "crashing" during program initialization.
Sometimes simply adding or removing code helps.
That being said, I would venture to suggest that this may be due to a paging error - a tight page boundary - or something similar.
A bit of an annoying bug, because it forces you to combine things.
I've been fascinated by Pascal compiler sources literally for decades (I started back around 1979). So when I found yours - among a few others - I was quite excited and I am quite impressed. I would like to ask a few questions.
Thank you for your attention.
Paul
"Understanding of things by me is only made possible by people — who read my comments — like you."
Thank you.
Paul Robinson [email protected]
The address operator @
works incorrectly on record fields.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version d5f34db
Mad-Assembler version 40bfd80
See also #90.
uses crt;
type
Vector = record x, y: Byte end;
Segment = record v1, v2: Vector end;
VectorPtr = ^Vector;
var s: Segment;
procedure PutVector(v: VectorPtr; x, y: Byte);
begin
v^.x := x;
v^.y := y;
end;
begin
PutVector(@s.v1, 1, 2);
PutVector(@s.v2, 3, 4);
WriteLn(s.v1.x, ' ', s.v1.y);
WriteLn(s.v2.x, ' ', s.v2.y);
ReadKey();
end.
1 2
3 4
3 4
0 0
Suddenly I got this message during compilation:
rol #$00
"Illegal addressing mode (CPU 6502)"
This is for the following source line:
vol_dist[winShift+winPos]:=(vol_dist[winShift+winPos] and $0f) or (v shl 4);
Compilation result:
; optimize OK (instrument.inc), line = 346
lda WINSHIFT
add WINPOS
sta :STACKORIGIN+9
lda WINSHIFT
add WINPOS
tay
lda adr.VOL_DIST,y
and #$0F
sta :STACKORIGIN+10
lda V
sta :STACKORIGIN+11
lda WINPOS+1
asl :STACKORIGIN+11
rol @
sta :STACKORIGIN+STACKWIDTH+11
rol #$00 <--- it's here
rol #$00
asl :STACKORIGIN+11
rol :STACKORIGIN+STACKWIDTH+11
asl :STACKORIGIN+11
rol :STACKORIGIN+STACKWIDTH+11
asl :STACKORIGIN+11
rol :STACKORIGIN+STACKWIDTH+11
lda :STACKORIGIN+10
ora :STACKORIGIN+11
ldy :STACKORIGIN+9
sta adr.VOL_DIST,y
I'll add that I didn't change anything at this point and this (source) code worked. What is wrong?
uses crt;
var
foo1: array[0..1] of byte;
foo2: PByte;
begin
foo2 := foo1;
foo2[0] := 5;
writeln(foo2[0]);
Inc(foo2[0]);
writeln(foo2[0]);
end.
works with Free Pascal but Mad Pascal shows:
test.pas (14,11) Error: Syntax error, ')' expected but '[' found
When a pointer to a record having nested record is passed to a procedure as a pointer then an attempt to copy such nested record to a local field yields compilation error.
For FPC -MDelphi v3.2.2 it works as expected.
Mad-Pascal Compiler version 9cc0813
Mad-Assembler version 40bfd80
uses crt;
type
Point = record x, y: Byte end;
Segment = record a, b: Point end;
SegmentPtr = ^Segment;
var s: Segment;
procedure DoSomething(sp: SegmentPtr);
var a, b: Point;
begin
// (1)
a := sp^.a;
b := sp^.b;
// (2)
// a := sp.a;
// b := sp.b;
WriteLn(a.x, ' ', a.y);
WriteLn(b.x, ' ', b.y);
end;
begin
s.a.x := 1; s.a.y := 2;
s.b.x := 3; s.b.y := 4;
DoSomething(@s);
ReadKey();
end.
1 2
3 4
(1)
test.pas (14,6) Error: Incompatible type of SP
(2)
ZPAGE: $0080..$00D3
RTLIB: $2000..$20BD
SYSTEM: $20E6..$20E9
CRT: $20EA..$20F0
CODE: $2000..$2194
DATA: $219C..$21C1
MVA ADR.SP.A+# ADR.A+#
test.a65 (436) ERROR: Undeclared label ADR.SP.A (BANK=0)
MVA ADR.SP.B+# ADR.B+#
test.a65 (445) ERROR: Undeclared label ADR.SP.B (BANK=0)
https://www.freepascal.org/docs-html/ref/refsu16.html
Zbiory to cecha charakterystyczna paskala...
keep
as modifier could be a compiler directive - this would be useful not to remove unnecessary in his opinion procedures or functions and maybe even data.
procedure foo; keep;
begin
end;
samples/demoeffects/spiral.pas
Adding to a pointer doesn't work in Mad-Pascal while it does in FPC.
uses crt;
var
a: array [0..1] of Byte = (2, 3);
p: ^Byte = @a;
begin
WriteLn(Word(@a));
WriteLn(Word(@a[0]));
WriteLn(a[0], ' ', a[1]);
WriteLn;
WriteLn(Word(p));
WriteLn(Word(Pointer(p)));
WriteLn(Byte((Pointer(p)+0)^), ' ', Byte((Pointer(p)+1)^)); // (1)
ReadKey();
end.
OS: Ubuntu 20.04.3 x86_64
FPC 3.2.2
Output:
59424
59424
2 3
59424
59424
2 3
Mad-Pascal Compiler version cca6b6f
Output:
Compiling ./test1.pas
./test1.pas (14,27) Error: Incompatible types: got "BYTE" expected "POINTER"
org [a($1001),a($100b),a(10),$9e,c'4109',t(0)],$100d
https://github.com/zbyti/mads-headers/blob/master/plus4-mads-header-full.asm
following code gives ambigious results:
var i,sep:byte;
t:string;
begin
t:='abcdefgh:ijklmnoprs';
for i:=1 to 17 do
if t[i] = ':' then
sep := i;
Writeln(sep);
for i:=1 to 17 do
if t[i] = ':' then begin
sep := i;
Pause;
end;
Writeln(sep);
for i:=1 to 17 do
if t[i] = ':' then
sep := i;
Pause;
Writeln(sep);
repeat until false;
end.
var
joy : byte absolute $ff08;
pio : byte absolute $fd30;
begin
repeat
pio := $ff;
joy := 2;
if (joy xor $ff) = 1 then writeln('UP');
until false;
end.
; --- RepeatUntilProlog
l_005B
; optimize OK (test.pas), line = 7
lda #$FF
sta PIO
; optimize OK (test.pas), line = 8
lda #$02
sta JOY
; optimize OK (test.pas), line = 10
eor #$FF
cmp #$01
jne l_0079
@printSTRING #CODEORIGIN+$0000
@printEOL
l_0079
; optimize OK (test.pas), line = 11
jmp l_005B
var
COLORRAM : array [0..0] of byte absolute $0800;
SCREEN : array [0..0] of byte absolute $0c00;
BORDERCOLOR : byte absolute $ff15;
BGCOLOR : byte absolute $ff19;
var
w0i, row : word;
b0i, b1i, x, c : byte;
begin
BORDERCOLOR := 0; BGCOLOR := 0;
FillByte(@SCREEN, 40 * 25, $a0);
for b0i := 0 to 7 do begin
row := 40 * b0i * 2;
for b1i := 0 to 15 do begin
x := b1i * 2; c := b0i shl 4 + b1i;
COLORRAM[row + x] := c; COLORRAM[row + x + 1] := c;
COLORRAM[row + 40 + x] := c; COLORRAM[row + 40 + x + 1] := c;
end;
end;
repeat until false;
end.
var
COLORRAM : array [0..0] of byte absolute $0800;
SCREEN : array [0..0] of byte absolute $0c00;
BORDERCOLOR : byte absolute $ff15;
BGCOLOR : byte absolute $ff19;
var
w0i, row : word;
b0i, b1i, x, c : byte;
begin
BORDERCOLOR := 0; BGCOLOR := 0;
FillByte(@SCREEN, 40 * 25, $a0);
for b0i := 0 to 7 do begin
row := 40 * b0i * 2;
for b1i := 0 to 15 do begin
x := b1i * 2; c := b0i shl 4 + b1i;
//COLORRAM[row + x] := c; COLORRAM[row + x + 1] := c;
Poke($0800 + row + x, c); Poke($0800 + row + x + 1, c);
//COLORRAM[row + 40 + x] := c; COLORRAM[row + 40 + x + 1] := c;
Poke($0800 + row + 40 + x, c); Poke($0800 + row + 40 + x + 1, c);
end;
end;
repeat until false;
end.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.