Jump to content
IGNORED

CC65 uploader configuration


LX.NET

Recommended Posts

Hi everyone (and Karri in particular ;) ),

 

Investigating the ComLynx functionality I found that the uploader functionality from the BLL toolkit has been ported to the CC65 library. There is even a lynx-uploader.cfg linker configuration file that allows you to include the uploader in your project/game.

When I tried to use it, it compiled OK, but seemed to give weird results on hardware, and not provide the intended behavior.

 

Here are some facts:

  • Created a ComLynx to USB cable myself and tested it with S.I.M.I.S. and Zeus to find out I could upload .o games. That part works.
  • Used the -C lynx-uploader.cfg switch to compile and link my experiment project. Compiled OK.
  • Tried both with and without including the comlynx driver.

It seems as if the game is stuck after drawing the first screen. I noticed that the text that I render is cut-off at the bottom, as if the drawing suddenly stopped. That was with the comlynx driver. Without the rendering went OK, but the game did not react to an upload nor keypress, so seemed stuck as well.

 

Some questions:

  • Can you use other interruptor implementations together with the uploader?
  • What do you need to do to get the uploader in place? I couldn't see other things (from the uploader.s source) to do apart from using the configuration in the make file.
  • Anyone has a working implementation in CC65?

Thanks.

Edited by LX.NET
Link to comment
Share on other sites

oops

 

I really have to check the code first. Its a long time since I wrote it.

 

I am investigating further and noticed that you once posted on how you need to set up the baudrate/timers first. Still midway that exercise, but any info is welcome.

 

This is my current main routine:

void main(void) 
{	
  initialize();

  MIKEY.serctl = 0x10|0x04|0x01|0x40|0x08;
  //MIKEY.SERCTL = TxParEnable|TxOpenColl|ParEven|RxIntEnable|ResetErr;

  _UART_TIMER.reload = 0x01;
  _UART_TIMER.control = 0x18; // %00011000

  tgi_clear();
  tgi_outtextxy(10, 10, "Upload your game!");
  tgi_updatedisplay();
	
  wait_joystick();

  while (1) 
    ;
}

Alex

Link to comment
Share on other sites

I think I found a possible cause.

The UART irq is level sensitive instead of edge sensitive. It's a documented bug in the hardware. You have to clear the interrupt flag for timer 4 (via INTRST = $FD80) to avoid having the IRQ being triggered over and over again.

Here's the fragment in the BLL source from upload.m65 (confirmed to work):

;
; last action : clear interrupt
;
exit            lda #$10
                sta $fd80
                rts

Here you see the interrupt being cleared.

In the CC65 uploader.s source:

;
; last action : clear interrupt
;
exit:
	clc
        rts

The interrupt handling mechanism in CC65 is different and less low-level. So, under normal circumstances this would be enough. But in this case you have to additionally clear the interrupt flag explicitly.

I'll try and compile a version that has the additional calls.

It makes me wonder if uploader.s has ever worked.

Fingers crossed.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

I've been digging deeper into this and got things working. Except... I am not satisfied yet.

In my previous experiments I noticed that the Lynx would freeze on real hardware. Using Handybug.exe I debugged my way into the interruptor pipeline and found that the interruptor for the uploader was already executing, but the calls were going nowhere. With the map from the linker I was able to determine that the destination for the calls was correct. The interruptor code wasn't loaded yet. This figures, because it is not located in the resident memory segment "RAM", but in "UPLD".

At the moment I have the uploader working, but it has a big workaround: the interruptor is in the RAM segment and sits somewhere low in memory. This means that larger .o modules cannot be loaded as they will overwrite the uploader code.

To the best of my current knowledge I think that all code outside the RAM segment must be explicitly loaded by a call to lynx_load(filenr), as it will not reside in the first file (assuming you are using the micro loader as cart header).

So, here's a new list of questions:

  • Did the current lynx-uploader.cfg work at all?
  • Did the original uploader code use different segments, like the configuration suggests?
  • Does interruptor code always have to be in the resident memory (RAM segment)?
  • Is there a way to load non-RAM segments automatically at startup?

The last two questions are related and are meant to come to a solution.

Ideally, I would say that the overhead of the interruptor should be negligible unless we are actually listening for incoming ComLynx traffic. I think that a routine that will load the necessary code and turn on timer 4 is a good thing. That way you know when and where to use the upload (at a particular screen e.g.) and not have the upload segment loaded unless necessary.

 

So, everyone and Karri in particular (as the author of the original CC65 uploader port): your thoughts and answers are appreciated.

Link to comment
Share on other sites

My memory is not so good on this one but here we go....

 

The uploader used interrupts only to see if the MAGIC start sequence is there. After it is the code jumps to the uploader and will never return. It loads in all the code and jumps after thet to the start address.

 

Th uploader goes to its own top segment called UPLOADER that sits in top memory between the SCREENS and the usable RAM.

 

I don't remember how much I tested the code. But most likely it worked as it has been unchanged since the start.

 

The original uploader was on top of the ROM. But today I have the SCREEN buffers there.

 

The interruptor code could be anywhere afaik.

 

You need to modify the boot code for loading more than one segment at boot time.

 

SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader
__BLOCKSIZE__: type = weak, value = 1024; # cart block size
__EXEHDR__: type = import;
__BOOTLDR__: type = import;
__DEFDIR__: type = import;
__UPLOADER__: type = import;
}
MEMORY {
ZP: file = "", define = yes, start = $0000, size = $0100;
HEADER: file = %O, start = $0000, size = $0040;
BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__;
DIR: file = %O, start = $0000, size = 8;
RAM: file = %O, define = yes, start = $0200, size = $BD38 - __STACKSIZE__;
UPLDR: file = %O, define = yes, start = $BFDC, size = $005C;
}

BR,

 

Karri

Link to comment
Share on other sites

  • 10 years later...

Is 10 years fast enough? ;)

 

Lynx: Uploader implementation and configuration does not work · Issue #2369 · cc65/cc65 (github.com)  

 

I posted an issue and made a pull request to fix the IRQ issue and the feedback, plus did some work on the configuration. I also removed the reference to __BLOCKSIZE__ which is was split previously into __BANK0BLOCKSIZE__ and __BANK1BLOCKSIZE__. Some code in lynx-cart.s and lseek.s still referred to __BLOCKSIZE__, but not anymore.

 

Should this pull request be approved you can easily add the uploader functionality to your code. 

This requires loading the file with the implementation and starting the serial 4 timer and the SERCTL settings.
 

// Load file before enabling RX interrupt
lynx_load((int)&UPLOAD_FILENR);

MIKEY.timer4.control = 0x18; // ENABLE_RELOAD | ENABLE_COUNT;
MIKEY.timer4.reload = 1; // AUD_2;	
MIKEY.serctl = 0x10 | 0x04 | 0x01 | 0x08; // PAREN | TXOPEN | PAREVEN | RESETERR;

// Clear receive buffer
while ((MIKEY.serctl & 0x40) > 0)
{
	data = MIKEY.serdat;
}
// Enable interrupt for timer 4 serial rate
MIKEY.serctl = 0x40 | 0x10 | 0x04 | 0x01 | 0x08; // PAREN | TXOPEN | PAREVEN | RESETERR | RXINTEN;

 

Let me know what you think. Chime in on the discussion at the GitHub cc65 repository where relevant.

Thanks. 

  • Haha 1
Link to comment
Share on other sites

Changes have been merged into the main branch. On a new build of lynx.lib the new uploaded will be included. 

I am creating a writeup on the uploader details and how to include it in your cc65 code. 

 

  • Like 1
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...