Jump to content
IGNORED

Black screen & crash(?) when using _graphics() call in cc65


Recommended Posts

So I'm missing something here. If I try to use the _graphics() function in the Atari library in cc65 to open a bitmap mode (e.g., mode 8, aka ANTIC $F), my program crashes with a black screen. Am I missing something obvious, memory-related? (e.g., something I should drop in my "atari.cfg" file for my project) Thanks in advance...

Link to comment
Share on other sites

I would think if it's performed by library function or the OS then the 1K DList boundary wouldn't usually be a problem.

More likely the problem might be memory related as in not enough free Ram.

 

Depending on what mode you open you'll need up to 8K. Normal OS Gr. 0 uses about 1K. The free Ram has to be contiguous, and screen allocation usually takes place from the top of known Ram downwards.

 

A potential problem can be if you mess with the top of memory pointers, the OS assumes Ram ends on a 4K boundary, problems with DList crossing 1K or screen crossing 4K can occur if that's not the case.

 

Is there a return code from the call? The OS at least will give status codes in the event that not enough Ram is available.

 

Location $6A has the high address of the first non-Ram location. Some programs will move it downward to reserve memory up high for other uses.

Link to comment
Share on other sites

Should also have added -

when opening the screen or doing anything that needs hardware registers updated from the shadows in Ram, you need to ensure VBlank stage 2 processing isn't being inhibited by certain things like NMIEN bitsettings, IRQs disabled by SEI, CRITIC flag nonzero.

If you need to do any of those things, wait at least one frame after opening the screen and setting colours etc.

Link to comment
Share on other sites

Hi!,

So I'm missing something here. If I try to use the _graphics() function in the Atari library in cc65 to open a bitmap mode (e.g., mode 8, aka ANTIC $F), my program crashes with a black screen. Am I missing something obvious, memory-related? (e.g., something I should drop in my "atari.cfg" file for my project) Thanks in advance...

Please, read here: http://cc65.github.io/doc/atari.html#ss6.1

 

The not so short story, the CC65 runtime uses all the available memory at startup, reserving the C heap from below and locating the C stack at the top. So, altering the screen layout to a mode using more memory, the C stack is overwritten, making your program crash.

 

The solution, you have to inform the linker to reserve memory. If you use the "atarixl" target, you need to alter the program start address with "--start-addr 0x4000", if you use the "atari" target, you need to reserve memory at the top with "-D__RESERVED_MEMORY__=0x2000", both options to the "cl65" utility.

  • Like 2
Link to comment
Share on other sites

Hi!,

 

Please, read here: http://cc65.github.io/doc/atari.html#ss6.1

 

The not so short story, the CC65 runtime uses all the available memory at startup, reserving the C heap from below and locating the C stack at the top. So, altering the screen layout to a mode using more memory, the C stack is overwritten, making your program crash.

 

The solution, you have to inform the linker to reserve memory. If you use the "atarixl" target, you need to alter the program start address with "--start-addr 0x4000", if you use the "atari" target, you need to reserve memory at the top with "-D__RESERVED_MEMORY__=0x2000", both options to the "cl65" utility.

 

PERFECT! :) I had a feeling it was something like that. All of this stuff 'outside' of the C programming itself (well, and Makefiles) is new to me, and I've admittedly been struggling to understand the documentation. More examples would be lovely - I keep finding people's cool Atari cc65 games, and they're all GRAPHICS 0 text with a redefined font (e.g., "The Hunt") ;)

Link to comment
Share on other sites

 

I somehow only just discovered that. I haven't tried it yet, but I love that it supports multiple inputs. I've got an ST mouse (and an Amiga one now), and a Touch Tablet. :)

 

I've never used the graphics command in cc65. I've always defined my own dlist, and placed it and the screen via the linker configuration.

 

My problem is I haven't found a good tutorial on doing just that. Having been a BASIC, TBXL & Action! programmer all these years, I've had GRAPHICS/Graphics() as a crutch. I assume there's more to do that just point the display list at a block of memory, if one wants to have E: and S: devices available, for example. ;)

Link to comment
Share on other sites

YMMV: If you have maybe 2 hours to spare, set up a Lightspeed C development environment and put a few minutes into learning the interface. It is a much easier interface and consistent with everything else Atari you already know.

 

Meh, black screen on graphics call!

 

Lightspeed even has a way to interface code between Action! and C. I can't remember all the details since I moved to Turbo C on the MSDOS after only a month or two with Lightspeed. It it ground up built for the Atari and would be the shortest way to develop something that works.

Link to comment
Share on other sites

 

I somehow only just discovered that. I haven't tried it yet, but I love that it supports multiple inputs. I've got an ST mouse (and an Amiga one now), and a Touch Tablet. :)

 

 

My problem is I haven't found a good tutorial on doing just that. Having been a BASIC, TBXL & Action! programmer all these years, I've had GRAPHICS/Graphics() as a crutch. I assume there's more to do that just point the display list at a block of memory, if one wants to have E: and S: devices available, for example. ;)

Look at the source code of this game: http://www.baktra.wz.cz/software/culomin.html, especially the 5200 version (does not use custom linker to embed DLIST etc, only pure CC65 means). An example how to do some graphics without library routines.

Link to comment
Share on other sites

  • 4 years later...

I've hit what I think might be a related problem with using the atarixl config

If I try using a call to _graphics() with a non-zero value, the program crashes on exit of main().

My test program only just calls graphics modes and does a printf.

I have other test code that puts stuff on the screen.

 

So I can enter the graphics mode safely, but then the app crashes when it exits main.

 

I set the --start-addr 0x4000 in the linker options and I can see that the start address of the program has changed.

 

But I still crash when the program is exiting.

 

It seems to be crashing in relation to code to cleanup during program termination. It looks to be initiating some call dispatching into memory that according to the atarixl-xex.cfg file is labeled as HIDDEN_RAM.

 

Not really sure how it got there. I started to think maybe it was related to some hints of the documentation about needing to recompile the C standard libs, but that seems to be with the himem.cfg files and not these.

 

Here's the console out of Altirra when it traps me at the illegal instruction. (Which I am guessing the linker is using as a poison pill? Or maybe the OS is doing that, not sure.)

 

Looks like this is trying to do some serial IO after central IO? Not sure why it would be triggering these actions on exit of main and/or cleanup code.

 

Additionally, my motivation for using the atarixl config is because I want to use graphics mode 12. If I run the atari-xex.cfg the program does not crash on exist, but I cannot enter graphics mode 12. 

 

Any insights, ideas, or help would be much appreciated. 

 

(45358:  1, 18) A=00 X=00 Y=00 S=F9 P=B0 (N     )  4137: AE D8 55  _exit   LDX SP_save  [$55D8] = $F9
(45358:  1, 22) A=00 X=F9 Y=00 S=F9 P=B0 (N     )  413A: 9A                TXS
(45358:  1, 24) A=00 X=F9 Y=00 S=F9 P=B0 (N     )  413B: 20 AD 4B  excexit JSR donelib  [$4BAD] = $A0
(45358:  1, 47) A=00 X=F9 Y=00 S=F9 P=32 (    Z )  413E: AD DA 55          LDA $55DA    [$55DA] = $02
(45358:  1, 52) A=02 X=F9 Y=00 S=F9 P=30 (      )  4141: 85 52             STA LMARGN   [$52]
(45358:  1, 56) A=02 X=F9 Y=00 S=F9 P=30 (      )  4143: AD D9 55          LDA $55D9    [$55D9] = $40
(45358:  1, 61) A=40 X=F9 Y=00 S=F9 P=30 (      )  4146: 8D BE 02          STA SHFLOK   [$02BE]
(45358:  1, 65) A=40 X=F9 Y=00 S=F9 P=30 (      )  4149: AD 04 40          LDA APPMHI_save [$4004] = $00
(45358:  1, 69) A=00 X=F9 Y=00 S=F9 P=32 (    Z )  414C: AE 05 40          LDX $4005    [$4005] = $00
(45358:  1, 73) A=00 X=00 Y=00 S=F9 P=32 (    Z )  414F: 85 0E             STA APPMHI   [$0E]
(45358:  1, 76) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4151: 86 0F             STX APPMHI+1 [$0F]
(45358:  1, 79) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4153: AD 07 40          LDA PORTB_save [$4007] = $00
(45358:  1, 83) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4156: 8D 01 D3          STA PORTB    [$D301]
(45358:  1, 87) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4159: AD 06 40          LDA RAMTOP_save [$4006] = $00
(45358:  1, 91) A=00 X=00 Y=00 S=F9 P=32 (    Z )  415C: 85 6A             STA RAMTOP   [$6A]
(45358:  1, 94) A=00 X=00 Y=00 S=F9 P=32 (    Z )  415E: AD 02 40          LDA MEMTOP_save [$4002] = $00
(45358:  1, 98) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4161: AE 03 40          LDX $4003    [$4003] = $00
(45358:  1,102) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4164: 8D E5 02          STA MEMTOP   [$02E5]
(45358:  1,106) A=00 X=00 Y=00 S=F9 P=32 (    Z )  4167: 8E E6 02          STX MEMTOP+1 [$02E6]
(45358:  1,110) A=00 X=00 Y=00 S=F9 P=32 (    Z )  416A: 20 89 4D          JSR findfreeiocb [$4D89] = $A2
(45358:  2, 93) A=FF X=30 Y=FF S=F9 P=33 (    ZC)  416D: A9 03             LDA #$03
(45358:  2, 95) A=03 X=30 Y=FF S=F9 P=31 (     C)  416F: 9D 42 03          STA ICCMD,X  [$0372]
(45358:  2,100) A=03 X=30 Y=FF S=F9 P=31 (     C)  4172: A9 0C             LDA #$0C
(45358:  2,102) A=0C X=30 Y=FF S=F9 P=31 (     C)  4174: 9D 4A 03          STA ICAX1,X  [$037A]
(45358:  2,107) A=0C X=30 Y=FF S=F9 P=31 (     C)  4177: A9 00             LDA #$00
(45358:  2,109) A=00 X=30 Y=FF S=F9 P=33 (    ZC)  4179: 9D 4B 03          STA ICAX2,X  [$037B]
(45358:  3,  0) A=00 X=30 Y=FF S=F9 P=33 (    ZC)  417C: A9 0B             LDA #$0B
(45358:  3,  2) A=0B X=30 Y=FF S=F9 P=31 (     C)  417E: 9D 44 03          STA ICBAL,X  [$0374]
(45358:  3,  7) A=0B X=30 Y=FF S=F9 P=31 (     C)  4181: A9 55             LDA #$55
(45358:  3,  9) A=55 X=30 Y=FF S=F9 P=31 (     C)  4183: 9D 45 03          STA ICBAH,X  [$0375]
(45358:  3, 14) A=55 X=30 Y=FF S=F9 P=31 (     C)  4186: A9 03             LDA #$03
(45358:  3, 16) A=03 X=30 Y=FF S=F9 P=31 (     C)  4188: 9D 48 03          STA ICBLL,X  [$0378]
(45358:  3, 21) A=03 X=30 Y=FF S=F9 P=31 (     C)  418B: A9 00     L418B   LDA #$00
(45358:  3, 23) A=00 X=30 Y=FF S=F9 P=33 (    ZC)  418D: 9D 49 03          STA ICBLH,X  [$0379]
(45358:  3, 30) A=00 X=30 Y=FF S=F9 P=33 (    ZC)  4190: 20 56 E4          JSR CIOV     [$E456] = $FF
CPU: Illegal instruction hit: E45A
(45358:  3, 48) A=00 X=30 Y=FF S=F7 P=33 (    ZC)  E459: 00        SIOV    BRK

 

 

Edited by SteveC1331
Link to comment
Share on other sites

It is trying to cleanup, restore the MMU to the original state and re-open the E: device.

 

But it doesn't seem to do it well. It sets MEMTOP and RAMTOP to 0, and also PORTB to 0. This invites disaster.

The values are read from storage locations that were supposed to serve as a backup for the original values, but got overwritten.

But without source code or binary load file, hard to say what it is.

 

 

Link to comment
Share on other sites

6 hours ago, baktra said:

It is trying to cleanup, restore the MMU to the original state and re-open the E: device.

 

But it doesn't seem to do it well. It sets MEMTOP and RAMTOP to 0, and also PORTB to 0. This invites disaster.

The values are read from storage locations that were supposed to serve as a backup for the original values, but got overwritten.

But without source code or binary load file, hard to say what it is.

 

 

I'm using the atarixl-xex.cfg that comes with CC65. The address that is crashing is referenced in the .cfg in the HIDDEN_RAM section.

 

I guess I am surprised as to why it would be trying to reopen the E device. I'm guessing E device is an emulated drive?

As for what the code is doing, its all from the CC65 library. I did think it was strange it was writing zeros to a bunch of stuff.

 

So this probably has nothing to do with the start address? At least not directly? I would have expected that if there were problems with that either the screen memory would become corrupt or the program would crash before exiting.

 

My code is little more than this:

 

void main(void)
{
	_graphics(1);
}

With needed headers and config'd for the atarixl target and the start address value to the linker.

 

Not sure if that helps...

Link to comment
Share on other sites

Hi!

6 minutes ago, SteveC1331 said:

I'm using the atarixl-xex.cfg that comes with CC65. The address that is crashing is referenced in the .cfg in the HIDDEN_RAM section.

 

I guess I am surprised as to why it would be trying to reopen the E device. I'm guessing E device is an emulated drive?

As for what the code is doing, its all from the CC65 library. I did think it was strange it was writing zeros to a bunch of stuff.

 

So this probably has nothing to do with the start address? At least not directly? I would have expected that if there were problems with that either the screen memory would become corrupt or the program would crash before exiting.

 

My code is little more than this:

 


void main(void)
{
	_graphics(1);
}

With needed headers and config'd for the atarixl target and the start address value to the linker.

In cc65, you can't use the "_graphics()" function with a graphics mode that needs more memory than the default screen without reserving memory. You need to read and understand the Atari documentation regarding the atari.cfg and atarixl.cfg linker scripts and the memory layouts.

 

If you are using the atari target, you must reserve memory for the graphics mode using -Wl -D__RESERVED_MEMORY__=number , with the correct amount in bytes.

 

If you are using the atarixl target (that uses RAM bellow ROM to give your program more memory), you need to change the starting address, read at https://cc65.github.io/doc/atari.html#loadaddr

 

But, if you use only graphics modes with less or equal memory (graphics 0, 1, 2, 3 and 4) you don't need to reserve extra memory (See for example the table at 024.gif ).

 

This is a sample program using graphics mode 1, it will work in both atari and atarixl targets.

#include <atari.h>  // For _graphics
#include <unistd.h> // For write
#include <string.h> // For strlen

static unsigned char scr;
#define print(a) write(scr, a, strlen(a))


void main(void)
{
  scr = _graphics(1);
  print("hello CC65\n");
  print("~~~~~~~~~~\n");
  print("\n");
  print("PRESS ANY KEY");
  OS.ch = 255;

  while(OS.ch == 255);
}

 

Have Fun!

 

    Daniel.

 

  • Like 2
Link to comment
Share on other sites

5 minutes ago, dmsc said:

Hi!

In cc65, you can't use the "_graphics()" function with a graphics mode that needs more memory than the default screen without reserving memory. You need to read and understand the Atari documentation regarding the atari.cfg and atarixl.cfg linker scripts and the memory layouts.

 

If you are using the atari target, you must reserve memory for the graphics mode using -Wl -D__RESERVED_MEMORY__=number , with the correct amount in bytes.

 

If you are using the atarixl target (that uses RAM bellow ROM to give your program more memory), you need to change the starting address, read at https://cc65.github.io/doc/atari.html#loadaddr

 

But, if you use only graphics modes with less or equal memory (graphics 0, 1, 2, 3 and 4) you don't need to reserve extra memory (See for example the table at 024.gif ).

 

This is a sample program using graphics mode 1, it will work in both atari and atarixl targets.


#include <atari.h>  // For _graphics
#include <unistd.h> // For write
#include <string.h> // For strlen

static unsigned char scr;
#define print(a) write(scr, a, strlen(a))


void main(void)
{
  scr = _graphics(1);
  print("hello CC65\n");
  print("~~~~~~~~~~\n");
  print("\n");
  print("PRESS ANY KEY");
  OS.ch = 255;

  while(OS.ch == 255);
}

 

Have Fun!

 

    Daniel.

 

 

Thanks for the hints, but I've already read over that stuff. And as my previous post states, I changed the start address with the linker flag and can see it change the start address of the program.

 

I just took your sources and tried building and running them in my setup and I get the same crash.

 

here is the build command line stuff:

 

C:\cc65\bin\cc65.exe --verbose --debug-info  --target atarixl  src\main.c -o build\main.s

C:\cc65\bin\ca65.exe --verbose --debug-info  --target atarixl build\main.s -o build\main.o

C:\cc65\bin\ld65.exe -C C:\cc65\cfg\atarixl-xex.cfg -Ln build\cc65TextExperiments.lbl --dbgfile build\cc65TextExperiments.dbg --start-addr 0x4000 -o build\cc65TextExperiments.xex build\main.o C:\cc65\lib\atarixl.lib

 

I picked the --start-addr from another post I read, hoping that would be a good example value as it was suggested in relation to the atarixl-xex.cfg

 

The thing is, it crashes even with _graphics(1) - anything other than zero. That was true even before I changed the start address. 

 

I just noticed the linker is giving me this warning:

 

ld65.exe: Warning: atari/crt0.s(207): 'lowcode area' reaches into $4000..$7FFF bank memory window

 

Maybe I'm setting the start address too high? Maybe that is just my problem...

 

I just building/running the example code you posted without the --start-address being set and I still crash, but I don't get that warning from the linker.

 

I also tried using the atarixl.cfg, instead of atarixl-xex.cfg, and crashed in the same way.

 

Maybe I have something misconfigured in the Altirra emulator? 

 

I think I have something more fundamental messed up...

 

 

Link to comment
Share on other sites

Hi!

1 hour ago, SteveC1331 said:

Thanks for the hints, but I've already read over that stuff. And as my previous post states, I changed the start address with the linker flag and can see it change the start address of the program.

Yes, sorry for not noticing it.

1 hour ago, SteveC1331 said:

I just took your sources and tried building and running them in my setup and I get the same crash.

 

here is the build command line stuff:

 

C:\cc65\bin\cc65.exe --verbose --debug-info  --target atarixl  src\main.c -o build\main.s

C:\cc65\bin\ca65.exe --verbose --debug-info  --target atarixl build\main.s -o build\main.o

C:\cc65\bin\ld65.exe -C C:\cc65\cfg\atarixl-xex.cfg -Ln build\cc65TextExperiments.lbl --dbgfile build\cc65TextExperiments.dbg --start-addr 0x4000 -o build\cc65TextExperiments.xex build\main.o C:\cc65\lib\atarixl.lib

 

I picked the --start-addr from another post I read, hoping that would be a good example value as it was suggested in relation to the atarixl-xex.cfg

 

IMHO, it is easier to simply use the CL65 command, that will call CC65, CA65 and LD65 with the correct parameters:

cl65 -t atarixl -C atarixl-xex.cfg --start-addr 0x3800 -Osir -g -vm -m prog.map -Ln prog.lbl  prog.c -o prog.xex

That will compile prog.c for atarixl target, using the atarixl-xex.cfg linker config file, with starting address at $3800, with optimizations, with debugging information, with verbose map file, store the map file to prog.map, store the label file to prog.lbl and store the resulting program in prog.xex

 

Attached here is the resulting XEX, it works in the emulators here, please test it in your setup.

 

1 hour ago, SteveC1331 said:

The thing is, it crashes even with _graphics(1) - anything other than zero. That was true even before I changed the start address. 

 

I just noticed the linker is giving me this warning:

 

ld65.exe: Warning: atari/crt0.s(207): 'lowcode area' reaches into $4000..$7FFF bank memory window

 

Maybe I'm setting the start address too high? Maybe that is just my problem...

That warning is benign, it says that your code is over the $4000 to $7FFF memory region, that region is the bank-switch window for the 128k (or more) memory expansions. As you are not using extended memory, the program will work.

 

1 hour ago, SteveC1331 said:

I just building/running the example code you posted without the --start-address being set and I still crash, but I don't get that warning from the linker.

 

I also tried using the atarixl.cfg, instead of atarixl-xex.cfg, and crashed in the same way.

 

Maybe I have something misconfigured in the Altirra emulator? 

Could be, or your CC65 libraries are somewhat corrupted.

 

Have Fun!

 

prog.xex

Link to comment
Share on other sites

5 minutes ago, dmsc said:

Hi!

Yes, sorry for not noticing it.

 

IMHO, it is easier to simply use the CL65 command, that will call CC65, CA65 and LD65 with the correct parameters:


cl65 -t atarixl -C atarixl-xex.cfg --start-addr 0x3800 -Osir -g -vm -m prog.map -Ln prog.lbl  prog.c -o prog.xex

That will compile prog.c for atarixl target, using the atarixl-xex.cfg linker config file, with starting address at $3800, with optimizations, with debugging information, with verbose map file, store the map file to prog.map, store the label file to prog.lbl and store the resulting program in prog.xex

 

Attached here is the resulting XEX, it works in the emulators here, please test it in your setup.

 

That warning is benign, it says that your code is over the $4000 to $7FFF memory region, that region is the bank-switch window for the 128k (or more) memory expansions. As you are not using extended memory, the program will work.

 

Could be, or your CC65 libraries are somewhat corrupted.

 

Have Fun!

 

prog.xex 3.78 kB · 1 download

No worries - thanks for the help!

 

I just tried the prog.xex and I crash in the same way, so most likely Altirra is misconfigured somehow? I'm going to re-download Altirra and try to reset it...

Link to comment
Share on other sites

Ok, I re-downloaded the Altirra software and tried again. Same result. I started to think maybe I was on to something because I had 'stop on BRK' set on in the Altirra options, I turned that off but then I remembered that it is crashing on illegal instruction, so I tried flipping that setting, to no avail. I tried disabling BASIC at launch, same result. 

 

I finally figured out my essential problem - I have been using the default AltirraOS 3.17 for XL/XE/XEGS internal ROM and associated BASIC.

 

I switched to the Atari XL/XE OS Ver.2 (and it's BASIC) and now the attached prog.xex runs without crashing and so do my test apps I am creating.

 

I know I don't need the BASIC enabled, but I was just trying to be consistent initially.

 

So it did turn out to be my emulator config, I guess I should be more skeptical of using emulator ROMs.

 

Thanks much @dmsc and everyone else - much appreciated!

Link to comment
Share on other sites

Hi!

20 minutes ago, SteveC1331 said:

Ok, I re-downloaded the Altirra software and tried again. Same result. I started to think maybe I was on to something because I had 'stop on BRK' set on in the Altirra options, I turned that off but then I remembered that it is crashing on illegal instruction, so I tried flipping that setting, to no avail. I tried disabling BASIC at launch, same result. 

 

I finally figured out my essential problem - I have been using the default AltirraOS 3.17 for XL/XE/XEGS internal ROM and associated BASIC.

 

I switched to the Atari XL/XE OS Ver.2 (and it's BASIC) and now the attached prog.xex runs without crashing and so do my test apps I am creating.

 

I know I don't need the BASIC enabled, but I was just trying to be consistent initially.

 

So it did turn out to be my emulator config, I guess I should be more skeptical of using emulator ROMs.

You could report this to @phaeron and if it turns to be a bug in the CC65 library, fill a bug in the cc65 github.

 

Thanks!

 

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