Jump to content

Greg King

  • Posts

  • Joined

  • Last visited

  • Days Won


Community Answers

  1. Greg King's post in Low framerate when mixing two PCM streams was marked as the answer   
    Your code waits for VSYNC, then does its work.  It finishes just in time to catch the next VSYNC.  If you add a little bit of code, then it can't finish in time -- it just misses the next VSYNC.  Maybe, your code must wait for the second next VSYNC!  It does nothing for almost an entire frame!  Naturally, its frame rate suffers a huge hit.
    (Try not waiting for VSYNC.  See what that does to the rate.)
  2. Greg King's post in lda #(^VRAM_addr + 2) ? was marked as the answer   
    No, the addition must be done last.  It's used to move past numbers that Commodore already used to control Kernal's LOAD behavior:
    0 -> normal load 1 -> normal verify 2 -> VRAM address high bit (0) 3 -> VRAM address high bit (1)
  3. Greg King's post in How to obtain the lobyte and hibyte of a word in cc65 (using macros?) was marked as the answer   
    What cc65 does depends on the context (the code that surrounds those expressions).  Most of the time, cc65 can recognize that they are simple byte fetches.  It won't do the actual operations that are implied by the C code.  cc65 will generate Assembly code that grabs the register that holds the desired byte.
    #define BYTE1(val) ((unsigned char)((val) & 0xFF))
    #define BYTE2(val) ((unsigned char)(((val) >> 8 ) & 0xFF))
    #define BYTE3(val) ((unsigned char)(((val) >> 16) & 0xFF))
    #define BYTE4(val) ((unsigned char)(((val) >> 24) & 0xFF))
  4. Greg King's post in R39 breaking cc65 code was marked as the answer   
    As Stephen wrote, cc65's R39 library is "waiting in the wings".  You can see it at https://github.com/greg-king5/cc65/tree/commander-r39.
  5. Greg King's post in Reading byte by byte in cc65 was marked as the answer   
    Yep.  LOAD and SAVE are the only things that you can do on the host's file-system.  If you really want to avoid those extra bytes, then you must work with an SD card image.  You had the right idea with cbm_read().  Here's some example code:
    #include <stdint.h> #include <stdio.h> #include <peekpoke.h> #include <cbm.h> #include <errno.h> uint8_t readbin2bank(char name[], uint8_t bank) {     uint8_t err;     int len;     POKE(REG_RAMBANK, bank);     err = cbm_open(2, 8, 2, name);     if (err != 0)     {         return err;     }     len = cbm_read(2, 0xA000, 0x2000);  // Read as much as allowed into current RAM bank.     if (len < 0)     {         cbm_close(2);         return _oserror;     }     printf("Read %d bytes into RAM bank %u.\n", len, bank);     cbm_close(2);     return 0; }
  6. Greg King's post in Changing directories in C program compiled with CC65 was marked as the answer   
    As you noticed, opendir() is a POSIX function.  It's intended to be portable.  The CBM implementation accepts only these string arguments:
    NULL "" "." "0:" "1:" But, there are also CBM-specific directory functions (prototyped in <cbm.h>):
    cbm_opendir() cbm_readdir() cbm_closedir()
  7. Greg King's post in cc65: switch to uppercase/petscii was marked as the answer   
    Your __asm__ version will work, but you forgot one thing: a "#" in front of the "$8E".
  8. Greg King's post in Some CC65 Questions was marked as the answer   
    I have improved two of the ld65 configure files ("cx16-asm.cfg" and "cx16-bank.cfg") because of your questions.  You should update your copy of the cc65 project's files.
    Answer about the original question 1:
    There are two available regions in the zero-page.  Each one should have its own definition in the MEMORY section of your .cfg file.  And, each one should have its own segment.  See how I did it in the new "cx16-asm.cfg" file.  You would start by putting your zero-page variables in the first segment.  When you tried to build your program, ld65 would complain that the memory area is too big; it would tell you how much too big.  Then, you would count that many bytes back from the end of your ZP variables, and insert a ".segment" line that names the other zero-page segment.
    Answer about the original question 2:
    You should use the ".res" method of defining those variables.  You should create a second file that has the same name as your zero-page source file, but with a suffix of ".inc" instead of ".asm".  That header file will use the .globalzp directive to export/import all of your ZP variables.  Your ZP source file will ".include" that header.  And, any other source file that needs to use those ZP variables will include that header.  That's one way that you can pass the names and locations from file to file.
    Other answers:
    "__LOADADDR__" and "__EXEHDR__" come from the system library.  (Their purpose is to force ld65 to link in some objects from that library.)  You don't write any code for them -- I already did that.  You tell ld65 about them by putting the library's name as the last one on the ld65 command line:
    ld65 -C x16-asm.cfg -o HELLO.PRG hello.o cx16.lib ld65 will find those names in that library, and it will link in the stuff for the main load address and the BASIC SYS stub.  Your main program should start with the "CODE" lines.  (As Ender wrote, cl65 gives the library name to ld65 for you; you don't need to remember it.)
    You're correct about Matt's "hello.asm" file.  ".org" lines must not be there!!  And, the ".segment" lines aren't needed by you -- because you aren't using "cx16.cfg".
    Yes, the cc65 project's "cx16-bank.cfg" is like "cx16.cfg".  It is written for C programs.  But, you can use it as an example template when you create the bank things in your .cfg file.
    __BANKRAMADDR__, also, would be imported from the system library.  But, you might create your own version of the "bankramaddr.s" file.  Therefore, don't put that line into your .cfg file.
    __HEADER_LAST__ and __ONCE_RUN__ are generated by ld65 because of "define = yes" attributes on some of the lines.  __HEADER_LAST__ is the address of the next byte after the actual end of the HEADER memory area.  Therefore, MAIN will start immediately after HEADER.  __ONCE_RUN__ is used as another way to create an overlay.  It is the address where the ONCE segment is put in RAM.  Therefore, BSS will be put on top of ONCE; that part of RAM will be reused.  The ONCE segment is useful for C program initiation, you don't need to care about it.
    The BSS segment is used for ".res" variables that you don't put into the zero-page.  RODATA is for data that never is changed (messages, for example).  DATA is for ".byte", ".word", and similar variables that must have specific values when the file is loaded, but that will be changed by the program.  Again, that separation mainly is for C programs, but Assembly code can use them, too.  ca65 has convenient nicknames for those ".segment" directives: ".zeropage", ".code", ".rodata", ".data", and ".bss".
    I recommend that you put the "__EXEHDR__" line in your .cfg file (if you haven't already).  (It will provide the BASIC SYS header.)
    I saw a $D000 in your .cfg file.  That's for the C64, not the X16!  I use the symbol name __HIMEM__ (high memory) to set the proper address -- you should do it as I did it.
  9. Greg King's post in BASIC Debuging Question was marked as the answer   
    You tripped over a big limitation of Micro BASIC.  It remembers only the first two characters of names!  The others are ignored.  When we execute
    we actually are running
    Therefore, your "many" variables are the same one: TA.
  10. Greg King's post in X16-demo basic scripts update for r37 was marked as the answer   
    I refered to the POKE at the end of line 20010.  But then, I looked at the "rom.sym" file in earlier releases.  I saw that
    :POKE 218,40
    told Kernal to pretend that the text screen has only forty rows.  I can't think of any reason to do that -- you should remove that statement.
    In early releases, text was put on layer 0, and graphics tended to be put on layer 1.  But, those roles have been swapped in the current release.  Therefore, you should plot the graphics on layer 0.
    Yes, the current raytracer.bas can't work on R35 and later releases.  You must go back to R34, in order to see it draw the picture (three mirror balls on a checkerboard).  But, be prepared to wait a very, very long time -- it's as slow as frozen molasses.
  11. Greg King's post in Address in basic-sprite demo was marked as the answer   
    The demo programs haven't been updated to R37.  You must use the documents in prerelease 36 when you study those programs.
  12. Greg King's post in What is the kernel call to check if there is a character? was marked as the answer   
    But, it returns the actual character if there is something in the buffer.
    Therefore, portable code must call GETIN, save the character, then return TRUE.  It first must check to see if there already is a saved character, and return TRUE immediately if there is something saved.  The KEY routine must call KEY? until that one returns TRUE, then return (and clear) that saved character.
  13. Greg King's post in assembly variables / two byte memory addressing was marked as the answer   
    Yep.  But in this case, it's three steps back.  😉
    There are two encodings: PetSCII and screen codes.  We print PetSCII to the screen.  But, we poke screen codes into screen RAM.  Therefore, you must change the text lines that you copy into VERA's VRAM.  Change the quotation marks into apostrophes.
        text    'In a wild and rough scrubland.'
  • Create New...

Important Information

Please review our Terms of Use