Jump to content

Greg King

  • Content Count

  • Joined

  • Last visited

  • Days Won


Greg King last won the day on June 28

Greg King had the most liked content!

Community Reputation

78 Excellent

1 Follower

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Currently, the increment/decrement must be or'ed into the address expression that's given to vpeek() and vpoke(). No one has taken the time to document a lot of the functions that are available in cc65's libraries. (Usually, someone finds a function in a header, learns that it's very useful to him, notices that it's not in the doc, then submits a patch to "funcref.sgml".) Yep. But, it isn't complete. For example, there are no constants for configuring sprites. "cx16.inc" (for Assembly programming) has much more of that stuff in it.
  2. #include <cx16.h> ... VERA.control = 0; VERA.address = address; VERA.address_hi = 1; VERA.data0 = the_byte; It compiles to the same Assembly code. But, it looks more C-like, less BASIC-like. cc65 also has vpeek() and vpoke() functions. They directly touch VRAM and internal registers.
  3. Those functions were designed for the mouse sprite. Its shape data is in the Kernal ROM. sprite_set_image is used to copy it into VRAM. sprite_set_position is used to move the mouse pointer during vertical blanking.
  4. Run the emulator. Use BASIC's MON command to start the monitor. Give the command "m fff0 ffff". You'll see it.
  5. This thread actually is about the mainboard version, not the Kernal version. This is the easiest way to test it, and switch to the Kernal bank: ; Assume BASIC ROM bank 4 at this point. stz $01 lda $FFF8 ; BASIC has zero, Kernal has nonzero bne mb2 stz $9F60 mb2: "stz $01" changes that location, but does nothing else, on mainboard #1. It changes to Kernal's bank on other mainboard versions. $FFF8 is a part of Kernal's "mist" signature. But, it's zeroes in the BASIC bank.
  6. The language in the description doesn't make it clear whether or not the LFO can do both modulations at the same time. Maybe, the F bit controls the output Function of the LFO (either it changes the frequency of another oscillator, or it changes the volume of that oscillator, but not both).
  7. That comment is about KickC. As I wrote earlier, cc65 works very differently.
  8. No. cc65's interrupt handling is much less efficient. It goes solely through the interrupt vector "daisy chain". Several independent handlers can be connected at the same time (if a handler is linked into a program, then it's connected automatically). Therefore, there's an extra layer that runs each handler, in turn. If you want to run C code in a handler, then another layer must be used to save and restore all of the housekeeping data that the compiler's runtime needs. Normal interrupt handling is slow -- not suitable for some video effects! If you want to stuff a lot of data into video RAM during the vertical blanking period, then your code must start as soon as possible, and run as fast as possible. Your program would need to intercept the interrupts manually. The handler should be written in Assembly code.
  9. There are two register lists: pseudo-registers (used by X16's Kernal) imaginary registers (used by LLVM-MOS) Be careful how much you overlap them! Imaginary register "__rs0" is used as the permanent soft-stack pointer.
  10. You cancel a VERA interrupt by writing the appropriate one-bit to the register: // end interrupt *VERA_ISR = VERA_LINE;
  11. I, also, don't understand why CMake doesn't recognize that they have different paths. However, I worked around it by renaming the new header -- output -- file to "cx16_header". (It needs to be renamed in both a CMakeLists.txt file and the link.ld script.)
  12. 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.
  13. In order to do what you want, your program needs two things: It needs to know when the vertical blanking is happenning. It needs to keep control of the computer. Your current code has number 1; but, number 1 can't work because it doesn't have number 2 (Kernal takes control and cancels number 1). Your program can get number 2 by temporarily preventing the CPU from seeing interrupts. The usual way in C code is to use a "SEI()" macro. Then, your code waits for the VSYNC flag. After it sees that flag, your code updates the menu. Then, it allows the CPU to notice interrupts again [a CLI() macro]. After that, your code gets player input, then possibly repeats the loop. [Notice that VSYNC() is done at the beginning of the loop, not at the end.] #define VSYNC() while (!(ISR & 1)) do { SEI(); VSYNC(); // Redraw the new menu. // And update the positions of "carots" and highlights. CLI(); // Handle input from the player. } while (!finished); How your code gets the SEI() and CLI() macros depends on which C compiler you're using (your code looks like KickC).
  14. He's right. I had assumed that Kernal checks for the vertical sync interrupt -- but, it doesn't!! Therefore, our programs are forced to do it. Your handler must have some additional code. __interrupt void myInterrupt(void) { if (*VERA_ISR & VERA_LINE) { vbcounter++; *VERA_IRQLINE_L = 100; *VERA_ISR = VERA_LINE; } else if (*VERA_ISR & VERA_VSYNC) { asm { jmp (default_irq_vector) } } // Other interrupts are ignored. } Note that the __interrupt qualifier makes this function return by jumping to R38 Kernal's $E049, which pulls the registers and does RTI.
  15. Your program does too much! Instead, it should follow these rules: Ignore interrupts that aren't important to the program. Your test program cares about only the raster line. Let Kernal handle the other interrupt. Don't constantly re-enable the interrupt. Set it once, at the beginning (it will stay enabled). After you handle the interrupt, clear only that interrupt! Always exit through the saved vector. Let Kernal do its things. #pragma target(cx16) #include <cx16.h> #include <6502.h> #include <string.h> #include <stdlib.h> #include <conio.h> #include <veralib.h> volatile char vbcounter=0; volatile void *default_irq_vector; __interrupt void myInterrupt(void) { if (*VERA_ISR & VERA_LINE) { vbcounter++; *VERA_IRQLINE_L = 100; *VERA_ISR = VERA_LINE; } asm { jmp (default_irq_vector) } } void initMain(void) { volatile unsigned char ll = 0, mm=0; default_irq_vector = *KERNEL_IRQ; SEI(); *KERNEL_IRQ = &myInterrupt; CLI(); *VERA_IRQLINE_L = 4; *VERA_IEN |= VERA_LINE; vpoke( 0,0, 0 ); // set "@" left top screen vpoke( 0,1, 0x12 ); // set "R" next to it while (1) { unsigned char c = kbhit(); if (c == 32) { vpoke( 0,0, ++mm ); // increment left top screen vpoke( 0,1, 0x12 ); // set "R" next to it } vpoke( 0,2, vbcounter ); vpoke( 0,3, 0x12 ); // set "R" next to it vpoke( 0,4, ll++ ); vpoke( 0,5, 0x12 ); // set "R" next to it } } void main(void) { initMain(); }
  • Create New...

Important Information

Please review our Terms of Use