Jump to content
IGNORED

10-liners for the Atari 5200? - FastBasic 4.6-beta is here!


Recommended Posts

Hi all,

 

I think that the Atari 5200 is under-represented in the BASIC 10-liners competition, so here is a new easy way to write games for the console:

 

Just released a new beta version of FastBasic, with one big addition: With the help of @vitoco, the PC compiler now supports the Atari 5200!

 

You can read the details in the manual at https://github.com/dmsc/fastbasic/blob/master/a5200.md , and the compiler usage in https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md

 

Basically, the Atari 5200 target supports:

- All the integer and string functions, including compatible STICK() and STRIG().

- Graphic modes 0, 1, 2, 7 to 13 and 15, with PLOT and DRAWTO support.

- DLI and P/M.

- PRINT to screen and GET for reading the Atari 5200 keypads.

 

To implement the Atari 5200 support, there are a lot of changes to the compiler under the hood, now the compiler supports multiple targets, and the old "integer only" and "floating-point" compilers are simply different targets now, the targets currently implemented are: Atari 8-bit computers binary loadable files (XEX, with and without floating point), Atari 8-bit computers Cartridge images (CAR, with and without floating point) and the new Atari 5200 Cartridge images (BIN).

 

Also, for advanced users, now the language can be extended without modifying the compiler sources, by writing new target files, there is an example in the compiler manual for writing a new statement and a new function, see https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md#extending-the-language 

 

There is a few new language extensions:

- TAB() function inside PRINT, moves to a column multiple of a number.

- DIM can be used to declare normal variables (like "DIM X$, Z"), the variables are automatically initialized to 0 or empty strings.

- The comma in prints now uses the TAB function internally, so it behaves more consistently in screen output (but in a different way that Atari BASIC).

 

Well, you can download all the usual files  from Github: https://github.com/dmsc/fastbasic/releases/tag/v4.6-beta

 

Attached is a test program, the "joyas" game ported to the Atari 5200 :)

 

Have Fun!

 

EDIT: final 4.6 version is released: 

 

 

joyas.bas joyas.bin

Edited by dmsc
Adds pointer to final version 4.6
  • Like 15
  • Thanks 3
Link to comment
Share on other sites

This really looks great!

 

I just started to dig into the new structure with the extensibility. What does "importzp" mean? I haven't done 6502 assembly in 35 years and only assembled/linked manually on paper .. so I might missed that bit.

 

Thanks

Steve

 

Link to comment
Share on other sites

Hi!

5 hours ago, SteveB said:

This really looks great!

 

I just started to dig into the new structure with the extensibility. What does "importzp" mean? I haven't done 6502 assembly in 35 years and only assembled/linked manually on paper .. so I might missed that bit.

The FastBasic PC compiler uses the CA65 assembler, this directive is part of it's syntax: https://cc65.github.io/doc/ca65.html 

 

Specifically, the ".importzp" directive tells the assembler that there is a symbol in some other source file or library that names a zero-page location - that is the same as saying that the symbol value is from 0 to 255. The assembler does not insert the value in the output directly, but a reference that the linker (LD65) fills up when building the resulting binary.

 

Have Fun!

Link to comment
Share on other sites

I try to create some common routines and from your manual I have two open questions:

  1. How do you handle parameters? Your example WAIT 40 / WAIT 80 uses a TOK_NUM. Is this the parameter? How do I handle multiple parameters? I looked into the included syntax files where in Graphics.syn you use 
    "DRawto" POSITION emit { TOK_BYTE, DRAWLN, TOK_DRAWTO }
    How is the POSITION handed over to the TOK_DRAWTO? I find "POSITION:   EXPR C_EXPR emit TOK_POSITION" in basic.syn ... is TOK_POSITION defined as X,Y in the compiler?
    How would I make a new statement with a mumber and a string?
     
  2. If my routine needs a variable, the assembler listing contains
        .byte    TOK_VAR_STORE 
        makevar    "VarName" "
    Can I use this also in the syntax file? Do I need to write in assembly if I need loops, temporary variables etc?

Thank you

Steve

 

Link to comment
Share on other sites

Hi!

 

First, the questions you are asking are fairly advanced about how FastBasic works, and IMHO, knowing 6502 assembly and a little about parsers and compilers is needed to fully appreciate the responses.

 

16 hours ago, SteveB said:

I try to create some common routines and from your manual I have two open questions:

  1. How do you handle parameters? Your example WAIT 40 / WAIT 80 uses a TOK_NUM. Is this the parameter? How do I handle multiple parameters? I looked into the included syntax files where in Graphics.syn you use 
    "DRawto" POSITION emit { TOK_BYTE, DRAWLN, TOK_DRAWTO }
    How is the POSITION handed over to the TOK_DRAWTO? I find "POSITION:   EXPR C_EXPR emit TOK_POSITION" in basic.syn ... is TOK_POSITION defined as X,Y in the compiler?
    How would I make a new statement with a mumber and a string?
  2. If my routine needs a variable, the assembler listing contains
        .byte    TOK_VAR_STORE 
        makevar    "VarName" "
    Can I use this also in the syntax file? Do I need to write in assembly if I need loops, temporary variables etc?

1) There are a few details in how the VM stores integer parameters:

- The *last* parameter is stored in the registers A and X (A holds the lower 8 bits, X holds the upper 8 bits).

- Other parameters are stored in the interpreter stack, the Y register holds the stack pointer, the low part is in "stack_l, y" and the high part in "stack_h, y".

 

For example, the "EXOR" operator is implemented as:

        eor     stack_l, y
        pha
        txa
        eor     stack_h, y
        tax
        pla
        jmp     next_ins_incsp

The last instruction increments the stack pointer (dropping the parameter there) and the result is returned in the registers AX.

 

If you look at the generated code, it will show instructions to load the parameter into the AX registers and the stack, but those instructions will depend on the BASIC code you wrote. For example, if you write "X EXOR 1", the compiler need to put the value of the variable "X" in the stack and the number "1" in the register AX, then call the "EXOR" operator as seen above - this is all implemented by the compiler by following the syntax rules, you don't need to worry about this.

 

In your example, you wrote "WAIT 40", so the compiler nee to emit code that loads the number "40" into the register AX first, to do that it uses the "TOK_NUM" operation, this "loads the 16 bit constant number into registers AX".

 

2) The "PLOT", "DRAWTO" and "FILLTO" code s different (and more complicated), because the Atari OS CIO code needs:

 - the (16-bit) X coordinate stored into "COLCRS"

 - the (8-bit) Y coordinate into "ROWCRS"

 - the CIO command byte set to "DRAWTO" or "FILLTO" depending on the operation.

 

As the initialization of X and Y coordinates is the same that the "POSITION" statement does, so the compiler simply reuses the parsing of "POSITION" to implement that. This makes the code smaller (and simpler).

 

And for the command byte, FastBasic emits the same code for both DRAWTO and FILLTO, but loading the byte "DRAWLN" or "FILLIN" into register A as appropriate before calling the DRAWTO operation.

 

3) In the parser, the "EXPR" you use simply parses and emits code that gets an integer expression (that can be as complicated as needed) into the registers AX. The "C_EXPR" simply expects a comma, emits code that stores the AX registers into the interpreter stack and then parses and emits code for a new integer expression into registers AX.

 

The above means that if the syntax file says " EXPR C_EXPR ", then the parser will expect two integer expressions separated by a comma and emit code that stores the first into the interpreter stack and the second in the registers AX, effectively implementing the calling convention that I explained before.

 

4) If you need to parse a string expression, you use "STR_EXPR" to get the pointer to the resulting string into registers AX. Strings are stored as one byte with the length followed by N bytes with the data.

 

Note that if you need an integer and a string, separated by commas, you need to be explicit about this (as there is no abbreviation for this combination in the parser): 

EXPR "," emit { TOK_PUSH } STR_EXPR

So, the code emitted will be "get the first expression into AX", then "push the value of AX into the stack", then "get the string address into AX".

 

If you implement a new statement that can get a string, you must support "null strings", in those the value of AX is 0. The interpreter "cheats" about it, by ensuring that memory location 0 holds a 0, this means that it looks as a 0 length string. Also, string expressions are "read-only", you can't modify the string being passed.

 

5) If you need to add a statement that expects a variable to store a value (like "GET X"), you need to tell the parser to pass the address of a variable (or array) instead of the value. The best way to do this is with the syntax rule "VAR_WORD_LVALUE_SADDR".

 

That rule emits code that loads the address of a word into a memory location called "SADDR" - an "l-value" in computer languages means "any expression that can be at the left of an equal sign". You can then use code like "ldy $0 / sta (SADDR), y" to store values into that.

 

There is also a rule named "VAR_STR_LVALUE_SADDR", that loads into "SADDR" the address of a string to be written to.

 

6) The parser can't create new arbitrary variables, it only can search/use/define variables whose name appears in the BASIC source being compiled. This makes sense if you think that the parser is called independently on each line, it does not store state from one line to the next. All the state is stored in a few outside tables: the list of variables, the list of labels and the list of loops.

 

So, if you add a new statement or function to the language, most of the code will probably need to be in a new assembly file.

 

There are a few things that you can do without assembly, for example you could add an statement to call SIO functions, and simply emit code that writes the needed values to the DCB using POKES and then calls the SIO vector.

 

Hope it makes all more clear.

 

Have Fun!

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Thank you very much! You basically confirmed my conclusions and explained the background very well. 

 

I will play around a little with all the information you gave and then decide if I want to go all the way or just build a "library" of FastBasic routines to manually include when needed. 

Link to comment
Share on other sites

Hi!

1 minute ago, eflake said:

in the example PMTEST.BAS, why do the sides of the outside of the border - dli? tend to flicker in altirra, when the ball nears the top or bounces on the sides of the top. 

Because those are not DLI, the background color is changed from the BASIC code after moving the player, showing the amount of CPU time spent in the BASIC code each frame; this CPU time is bigger when the ball bounces, because the code needs to update the ball speed.

 

Have Fun!

  • Like 1
Link to comment
Share on other sites

Hi,

 

I found a glitch or nasty feature ... I use fastbasic.exe on Windows in a selfmade toolchain. With version 4.5.2 I could redirect the output and errors using >, >> or |, just like with other commandline tools. This is not possible anymore with 4.6. beta. This is a problem when there is an syntax-error in your basic source and you want to scan the output for the error. Can you write the compiler errors again to standard-output ? If you can't pass the output from your sub-commands CA65 and LD65 this would be okay for me, but not getting the hint, where the error in my source is, makes it difficult. 

 

You can check this by "fastbasic test.bas >output.txt" ... output has allways 0 bytes.

 

Thank you

Steve

Link to comment
Share on other sites

Hi!

On 3/23/2022 at 5:45 PM, SteveB said:

I found a glitch or nasty feature ... I use fastbasic.exe on Windows in a selfmade toolchain. With version 4.5.2 I could redirect the output and errors using >, >> or |, just like with other commandline tools. This is not possible anymore with 4.6. beta. This is a problem when there is an syntax-error in your basic source and you want to scan the output for the error. Can you write the compiler errors again to standard-output ? If you can't pass the output from your sub-commands CA65 and LD65 this would be okay for me, but not getting the hint, where the error in my source is, makes it difficult. 

 

You can check this by "fastbasic test.bas >output.txt" ... output has allways 0 bytes.

The compiler outputs error messages to standard-error, so you must redirect with "2>" instead of ">", tested with:

C:\Users\daniel\tst>fastbasic 2> output.txt

 

I don't know why it worked before, perhaps the BAT file that called the compiler did the redirection? Newer versions don't use a BAT file, the compiler itself calls the assembler and linker.

 

Have Fun!

Link to comment
Share on other sites

This is a little embarrassing for me now ... I assumed at least "BAS compile 'test.fbas' to 'test.asm'" would be on stdout. Your new fastbasic.exe is more convinient to use and I rewrote the code for the beta, dropping all the CA65 and LD65 code now obsolete ... I won't do a restore to check what I had implemented for the three seperate programs... ?

 

I have fun with the beta! Works great for me.

 

Thank you 

Steve

Link to comment
Share on other sites

  • 1 month later...

From the manual:

$(addr) : Returns the string at memory address addr

Would it be possible to use the $() also on the left side of an assignment? When I have the adress of a string in 'a' it would be handy to use '$(a) = "my new stringvalue". 

 

Link to comment
Share on other sites

Hi!

20 hours ago, SteveB said:

From the manual:


$(addr) : Returns the string at memory address addr

Would it be possible to use the $() also on the left side of an assignment? When I have the adress of a string in 'a' it would be handy to use '$(a) = "my new stringvalue". 

 

That is not possible, as the interpreter expects the address of the variable at the left hand of the =, because when assigning there is the need of allocate the memory to hold the string. The expression created by $() is only the address of the string data.

 

To copy to an already allocated string, you can do: MOVE ADR("my new stringvalue"), a, LEN("my new stringvalue") + 1, but you then must be careful that destination has enough space for the string data already.

 

Have Fun!

Link to comment
Share on other sites

On 3/1/2022 at 9:59 PM, dmsc said:

Hi all,

 

I think that the Atari 5200 is under-represented in the BASIC 10-liners competition, so here is a new easy way to write games for the console:

 

Just released a new beta version of FastBasic, with one big addition: With the help of @vitoco, the PC compiler now supports the Atari 5200!

 

You can read the details in the manual at https://github.com/dmsc/fastbasic/blob/master/a5200.md , and the compiler usage in https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md

 

Basically, the Atari 5200 target supports:

- All the integer and string functions, including compatible STICK() and STRIG().

- Graphic modes 0, 1, 2, 7 to 13 and 15, with PLOT and DRAWTO support.

- DLI and P/M.

- PRINT to screen and GET for reading the Atari 5200 keypads.

 

To implement the Atari 5200 support, there are a lot of changes to the compiler under the hood, now the compiler supports multiple targets, and the old "integer only" and "floating-point" compilers are simply different targets now, the targets currently implemented are: Atari 8-bit computers binary loadable files (XEX, with and without floating point), Atari 8-bit computers Cartridge images (CAR, with and without floating point) and the new Atari 5200 Cartridge images (BIN).

 

Also, for advanced users, now the language can be extended without modifying the compiler sources, by writing new target files, there is an example in the compiler manual for writing a new statement and a new function, see https://github.com/dmsc/fastbasic/blob/master/compiler/USAGE.md#extending-the-language 

 

There is a few new language extensions:

- TAB() function inside PRINT, moves to a column multiple of a number.

- DIM can be used to declare normal variables (like "DIM X$, Z"), the variables are automatically initialized to 0 or empty strings.

- The comma in prints now uses the TAB function internally, so it behaves more consistently in screen output (but in a different way that Atari BASIC).

 

Well, you can download all the usual files  from Github: https://github.com/dmsc/fastbasic/releases/tag/v4.6-beta

 

Attached is a test program, the "joyas" game ported to the Atari 5200 :)

 

Have Fun!

 

 

joyas.bas 13.27 kB · 27 downloads joyas.bin 32 kB · 24 downloads

Nice game !

 

  • Like 1
Link to comment
Share on other sites

On 3/10/2022 at 10:48 AM, dmsc said:

Hi!

 

First, the questions you are asking are fairly advanced about how FastBasic works, and IMHO, knowing 6502 assembly and a little about parsers and compilers is needed to fully appreciate the responses.

 

1) There are a few details in how the VM stores integer parameters:

- The *last* parameter is stored in the registers A and X (A holds the lower 8 bits, X holds the upper 8 bits).

- Other parameters are stored in the interpreter stack, the Y register holds the stack pointer, the low part is in "stack_l, y" and the high part in "stack_h, y".

 

For example, the "EXOR" operator is implemented as:


        eor     stack_l, y
        pha
        txa
        eor     stack_h, y
        tax
        pla
        jmp     next_ins_incsp

The last instruction increments the stack pointer (dropping the parameter there) and the result is returned in the registers AX.

 

If you look at the generated code, it will show instructions to load the parameter into the AX registers and the stack, but those instructions will depend on the BASIC code you wrote. For example, if you write "X EXOR 1", the compiler need to put the value of the variable "X" in the stack and the number "1" in the register AX, then call the "EXOR" operator as seen above - this is all implemented by the compiler by following the syntax rules, you don't need to worry about this.

 

In your example, you wrote "WAIT 40", so the compiler nee to emit code that loads the number "40" into the register AX first, to do that it uses the "TOK_NUM" operation, this "loads the 16 bit constant number into registers AX".

 

2) The "PLOT", "DRAWTO" and "FILLTO" code s different (and more complicated), because the Atari OS CIO code needs:

 - the (16-bit) X coordinate stored into "COLCRS"

 - the (8-bit) Y coordinate into "ROWCRS"

 - the CIO command byte set to "DRAWTO" or "FILLTO" depending on the operation.

 

As the initialization of X and Y coordinates is the same that the "POSITION" statement does, so the compiler simply reuses the parsing of "POSITION" to implement that. This makes the code smaller (and simpler).

 

And for the command byte, FastBasic emits the same code for both DRAWTO and FILLTO, but loading the byte "DRAWLN" or "FILLIN" into register A as appropriate before calling the DRAWTO operation.

 

3) In the parser, the "EXPR" you use simply parses and emits code that gets an integer expression (that can be as complicated as needed) into the registers AX. The "C_EXPR" simply expects a comma, emits code that stores the AX registers into the interpreter stack and then parses and emits code for a new integer expression into registers AX.

 

The above means that if the syntax file says " EXPR C_EXPR ", then the parser will expect two integer expressions separated by a comma and emit code that stores the first into the interpreter stack and the second in the registers AX, effectively implementing the calling convention that I explained before.

 

4) If you need to parse a string expression, you use "STR_EXPR" to get the pointer to the resulting string into registers AX. Strings are stored as one byte with the length followed by N bytes with the data.

 

Note that if you need an integer and a string, separated by commas, you need to be explicit about this (as there is no abbreviation for this combination in the parser): 


EXPR "," emit { TOK_PUSH } STR_EXPR

So, the code emitted will be "get the first expression into AX", then "push the value of AX into the stack", then "get the string address into AX".

 

If you implement a new statement that can get a string, you must support "null strings", in those the value of AX is 0. The interpreter "cheats" about it, by ensuring that memory location 0 holds a 0, this means that it looks as a 0 length string. Also, string expressions are "read-only", you can't modify the string being passed.

 

5) If you need to add a statement that expects a variable to store a value (like "GET X"), you need to tell the parser to pass the address of a variable (or array) instead of the value. The best way to do this is with the syntax rule "VAR_WORD_LVALUE_SADDR".

 

That rule emits code that loads the address of a word into a memory location called "SADDR" - an "l-value" in computer languages means "any expression that can be at the left of an equal sign". You can then use code like "ldy $0 / sta (SADDR), y" to store values into that.

 

There is also a rule named "VAR_STR_LVALUE_SADDR", that loads into "SADDR" the address of a string to be written to.

 

6) The parser can't create new arbitrary variables, it only can search/use/define variables whose name appears in the BASIC source being compiled. This makes sense if you think that the parser is called independently on each line, it does not store state from one line to the next. All the state is stored in a few outside tables: the list of variables, the list of labels and the list of loops.

 

So, if you add a new statement or function to the language, most of the code will probably need to be in a new assembly file.

 

There are a few things that you can do without assembly, for example you could add an statement to call SIO functions, and simply emit code that writes the needed values to the DCB using POKES and then calls the SIO vector.

 

Hope it makes all more clear.

 

Have Fun!

 

 

hi , can you please convert the other games to the 5200 ?

  • Confused 1
Link to comment
Share on other sites

  • 1 month later...

Hi!

5 hours ago, SteveB said:

The 4.6beta is now out for four months. Will there be a beta2 or when can we expect the final 4.6 release?

I was expecting feedback about the 5200 support before making the final release, but as this has not happened, I should simply release v4.6.

 

Will try to wrap this over the weekend.

 

Have Fun!

 

Link to comment
Share on other sites

I only own my 800XL I bought back in 1985 ... so I never tried to compile anything for the 5200 ... until now.

 

The game I am working on uses GRAPHICS 12+16 (should this be 12 only for the 5200?) and it looks like it does not recognise the "locate" command and mistake it for a variable:

repeat
  st = stick(0)
  a1 = a - 4*((st=10)+(st=11)+(st=9)-(st=5)-(st=6)-(st=7))
  b1 = b - 8*((st=10)+(st=14)+(st=6)-(st=5)-(st=13)-(st=9))
  locate a1/4-12,b1/8-4,c
  if c=32
    da=(a1-a)/4
.....

image.thumb.png.1fc0086bc9af0627e692fb76dd95e57a.png

 

But since this is my first attempt to compile for the 5200 this might be an error on my side.

 

Steve

 

Link to comment
Share on other sites

17 hours ago, dmsc said:

Hi!

I was expecting feedback about the 5200 support before making the final release, but as this has not happened, I should simply release v4.6.

 

Will try to wrap this over the weekend.

 

Have Fun!

 

 

I've wanted to dabble in 5200 development for some time but 5200bas is long dead and most BASIC topics here refer to Atari computers.  Just happened to catch this on the activity stream.  Holy cow!

 

Can't promise anything but figuring out how to set this up, compile and test 5200 games is now on my list of things to actually do.

Link to comment
Share on other sites

Hi!

Quote

I only own my 800XL I bought back in 1985 ... so I never tried to compile anything for the 5200 ... until now.

 

The game I am working on uses GRAPHICS 12+16 (should this be 12 only for the 5200?) and it looks like it does not recognise the "locate" command and mistake it for a variable:


repeat
  st = stick(0)
  a1 = a - 4*((st=10)+(st=11)+(st=9)-(st=5)-(st=6)-(st=7))
  b1 = b - 8*((st=10)+(st=14)+(st=6)-(st=5)-(st=13)-(st=9))
  locate a1/4-12,b1/8-4,c
  if c=32
    da=(a1-a)/4
.....

image.thumb.png.1fc0086bc9af0627e692fb76dd95e57a.png

 

But since this is my first attempt to compile for the 5200 this might be an error on my side.

 

Ah, I did not implement LOCATE for the A5200. I will add it and post a new compiler for you to test.

 

Also, keep in mind that I did not implement DRAWTO for text-modes. Do you use it?

 

Have Fun!

Edited by dmsc
Link to comment
Share on other sites

Hi!

 

And here is a new beta version, changes from old beta are:

 

Atari 5200 port:

- Allows I/O channel 6 in PRINT, INPUT and CLS, for compatibility with A800.

- Fixes sub-string accessing (i.e.,  A$ = B$[1,2] )

- Fixes bugs with INPUT statement.

- Fixes noises with SOUND.

- PTRIG now returns the state of the secondary button in the controllers.

- Adds LOCATE statement.

- Fixes GRAPHICS mode 7.

 

General:

- Makes MOVE/-MOVE faster.

- Adds RTAB() function to right-align the next argument in PRINT statements, use like: PRINT "Hello" RTAB(20) X

 

Cross-Compiler:

- Allows building Windows version native and ports the cross-compiler test-suite to Windows.

- Prints better compiler error messages.

- Allows defining symbols for the linker and passing arbitrary arguements.

 

Please try and report any bugs.

 

Have Fun!

fastbasic-v4.6-beta2-win32.zip fastbasic-v4.6-beta2-linux64.zip fastbasic-v4.6-beta2.atr

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

8 hours ago, dmsc said:

Hi!

 

Ah, I did not implement LOCATE for the A5200. I will add it and post a new compiler for you to test.

 

Also, keep in mind that I did not implement DRAWTO for text-modes. Do you use it?

 

Have Fun!

Thank you! 

 

I will test it later today and I do not use DRAWTO, but #6 output which I had to change. I can now revert to the 800 code!

Link to comment
Share on other sites

It compiles fine now, even with the "#6", but the graphics do not work.

 

1. PRINT in GRAPHICS 12 behaves differently than in 800 mode

 

2. My Charset routine, copying the charset and defining the "Tiles" does not work like on the XL:

PROC Charset
  CB=PEEK(756)*256
  NCB = (PEEK(106)-32)*256
  MOVE CB, NCB, 1024
  POKE 756,PEEK(106)-32
ENDPROC 
  
PROC CharDef c v0 v1 v2 v3 v4 v5 v6 v7
  c=(c-32)*8
  POKE NCB+c+0,v0
  POKE NCB+c+1,v1
  POKE NCB+c+2,v2
  POKE NCB+c+3,v3
  POKE NCB+c+4,v4
  POKE NCB+c+5,v5
  POKE NCB+c+6,v6
  POKE NCB+c+7,v7
ENDPROC    

As I do not use any Pokey, GTIA or Antic registers, I thought I was safe ... But font-handling seems to differ.

 

3. my P/M shows artefacts in the "unused" space, there seems to be a difference in initialization. I solved this with an additional "MSET PMADR(nr),256,0". Perhaps a good idea on my 800XL code as well.

 

Any Ideas?

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