I'm trying to squeeze my memory map as much as I can into low memory. For my setup I can assume the following:
- I'll never return to basic
- I setup my own IM2 routine
Code: Select all
$4000 - $5AFF -> SCREEN$ (as usual)
$5B00 - $5C00 -> My IM2 table goes here - IM2 vector is $5B, and I load it with 257 x $5C values
$5C5C - $5C5E -> JP <isr_routine> - I patch the JP opcode and the ISR address here
$5C5F - $5CFF -> Stack (162 bytes) - The stack ptr at start is then set to $5D00
$5D00 - up to SP1 data structs) - The C program
So for this setup I write the following code:
Code: Select all
// zcc +zx -vn -SO3 -m -compiler=sdcc -clib=sdcc_iy --max-allocs-per-node200000 main.c -o main.bin -startup=31 -create-app
#pragma output CRT_ORG_CODE = 0x5d00 // org of compile
#pragma output REGISTER_SP = 0x5d00 // just below code
#pragma output CRT_STACK_SIZE = 162 // just enough
#pragma output CRT_ENABLE_CLOSE = 0 // don't bother closing files on exit
#pragma output CRT_ENABLE_EIDI = 1 // disable interrupts at start
#pragma output CRT_ENABLE_RESTART = 1 // do not return to basic
#pragma output CLIB_MALLOC_HEAP_SIZE = 1024 // heap size
#pragma output CLIB_STDIO_HEAP_SIZE = 0 // no stdio heap (no files)
#pragma output CLIB_FOPEN_MAX = -1 // no FILE* list
#pragma output CLIB_OPEN_MAX = -1 // no fd table
#include <stdlib.h>
#include <im2.h>
#include <string.h>
#include <intrinsic.h>
#include <z80.h>
// data struct and ISR hook for timekeeping
struct time {
uint8_t hour, min, sec, frame;
} current_time = { 0, 0, 0, 0 };
// timer tick routine
IM2_DEFINE_ISR(do_timer_tick)
{
if ( ++current_time.frame == 50 ) { // 50 frames per second
current_time.frame = 0;
if ( ++current_time.sec == 60 ) {
current_time.sec = 0;
if ( ++current_time.min == 60 ) {
current_time.min = 0;
++current_time.hour;
}
}
}
}
// Initialize interrupts in IM2 mode
#define IV_ADDR ( (void *) 0x5b00 )
#define ISR_ADDR ( (void *) 0x5c5c )
#define IV_BYTE ( 0x5c )
#define Z80_OPCODE_JP ( 0xc3 )
void init_interrupts(void) {
intrinsic_di();
im2_init( IV_ADDR );
memset( IV_ADDR,IV_BYTE, 257 );
z80_bpoke( ISR_ADDR, Z80_OPCODE_JP );
z80_wpoke( ISR_ADDR + 1, (uint16_t) do_timer_tick );
intrinsic_ei();
}
void main(void) {
init_interrupts();
// Just make a small mark at the top of the screen
*(char*)0x4000 = 0xf2;
while (1);
}
But when I compile the above program and run it, It does not show the mark at the screen top, and returns to BASIC. Also the BASIC program is corrupt, since it was not supposed to return.
Can you give any hints about why this is not working?
Thanks
Jorge