Hi!
I will try to explain how to make an hybrid rom, containing both asm and basic programs, in order to get a final length longer than the standard 16kbs. The final ROM will be a 16kb ROM, but we will use compression, so we will get a 16kb basic prog in page 2, as usual, assembler routines in page 3 and, before execution, we can change the character set, colors, etc. (so we won't need to include it in our BASIC prog.) and, with a bit of luck, we may be able to include even a splash screen at startup
The game Manicomio uses this format. The idea is to pack all data in a 16kb ROM located at page 1. Then, decompress the basic program to page 2, so we will place our listing to the usual location for basic ROMs. But there's no Basic interpreter, as page 1 is used by the cartridge. So we need to switch pages in order to place the Basic interpreter working again. This cannot be done directly, as the basic interpreter would overwrite the cartridge and we will loose it and will not be able to do anything else
So we will place a switch-to-basic routine OUTSIDE pages 1 and 2 (occupied by basic listing), that's page 3, that will switch the pages and execute the basic command RUN.
Decompressing, installing asm routines, jumping to switch-to-basic routine in page 3 and executing the basic program. It seems there will be no problems
Steps we have to follow:
- Make your basic program not longer than 16kb, that is, we will use only the page 2. Use a clear 200,49151 g.e. in order to prevent this.
- Once loaded in memory, save your basic program with save (save your work first!) and then bsave"prog",32768,49151. I'm assuming that we use the entire page 2, but change it to the size of your prog if you want to. 32768, the initial direction of the basic program, is a must.
- Use your favourite hex editor and erase the first seven bytes of the resulting file. This will remove the header used by MS-DOS, not needed.
- Compress the file using bitbuster using "pack prog".
- Use the bindb utility from the asmsx package in order to obtain a plain text file from the compressed file. You can add it then to this snippet with a text editor.
- Place the resulting file in the snippet, where it belongs (as indicated). The same with your asm routines, etc.
;-------------------------------------------
; Hybrid ROM
;-------------------------------------------
.bios
.page 1
.rom
.start BEGIN
.size 16
;We will use this part to set screen mode, colors, etc.
BEGIN:
ld hl,0f3e9h
ld [hl],14
inc hl
ld [hl],1
inc hl
ld [hl],1 ;color 14,1,1
call CHGCLR
call INIT32 ;Screen 1
ld bc,0e201h
call WRTVDP ;Screen ,2
xor a
ld [f3dbh],a ;screen ,,0
ld hl,CHAR_SET
ld de,0
ld bc,2048
call LDIRVM ;Dump char set to VRAM
ld hl,SET_BASIC
ld de,55100
ld bc,120
ldir ;Copies the switch-to-BASIC
;routine to 55100, g.e.
jp 55100 ;Jumps to the BASIC program, finally!
;-------------------------------------------
;Switch to the BASIC program and run it
;-------------------------------------------
SET_BASIC: ;This routine switches the page 1, connecting
;the BASIC interpreter located in ROM
;Note this operation must be done in
;page 3, otherwise it would overwrite itself!
ld a,1
ld [fbb1h],a ;Indicates a BASIC prog is executed
ld hl,50799
ld [f672h],hl ;clear ,50799 in order to not overwrite the
;assembler routines, set at 50800
ld hl,ASSEMBLER ;Your asm routines will begin at 50800. You can
ld de,50800 ;change all this, of course.
call depack
ld hl,BASIC_PROG ;Beginning of the BASIC prog. (don't change it)
ld de,32768
call depack
di
call RSLREG
res 2,a
res 3,a
call WSLREG ;Switches to the BASIC interpreter
ei
ld a,1
ld [$FBB1],a
ld hl,[$F6C2]
ld de,$C000
rst $20
jr nc,@@JUMP
ex de,hl
ld [$F6C2],hl
@@JUMP:
jp $73AC ;Sets the correct variable pointer
jp 73ACh ;Executes RUN command. Here we go! :)
;---------------------------------
;BITBUSTER decompression routine
;---------------------------------
GET_BIT_FROM_BITSTREAM:
add a,a
jp nz,GET_BIT_FROM_BITSTREAMYM
ld a,[hl]
inc hl
rla
GET_BIT_FROM_BITSTREAMYM:
ret
depack: inc hl
inc hl
inc hl
inc hl
ld a,128
exx
ld de,1
exx
depack_loop:
call GET_BIT_FROM_BITSTREAM
jp c,output_compressed
ldi
call GET_BIT_FROM_BITSTREAM
jp c,output_compressed
ldi
call GET_BIT_FROM_BITSTREAM
jp c,output_compressed
ldi
jp depack_loop
output_compressed:
ld c,[hl]
inc hl
output_match:
ld b,0
bit 7,c
jr z,output_match1
call GET_BIT_FROM_BITSTREAM
rl b
call GET_BIT_FROM_BITSTREAM
rl b
call GET_BIT_FROM_BITSTREAM
rl b
call GET_BIT_FROM_BITSTREAM
jp c,output_match1
res 7,c
output_match1:
inc bc
exx
ld h,d
ld l,e
ld b,e
exx
call GET_BIT_FROM_BITSTREAM
exx
jr nc,get_gamma_value_size_end
inc b
jp get_gamma_value_size
get_gamma_value_bits:
exx
call GET_BIT_FROM_BITSTREAM
exx
adc hl,hl
get_gamma_value_size_end:
djnz get_gamma_value_bits
get_gamma_value_end:
inc hl
exx
ret c
push hl
exx
push hl
exx
ld h,d
ld l,e
sbc hl,bc
pop bc
ldir
pop hl
call GET_BIT_FROM_BITSTREAM
jp c,output_compressed
ldi
call GET_BIT_FROM_BITSTREAM
jp c,output_compressed
ldi
jp depack_loop
;----------------------------------
;Assembler routines
;----------------------------------
ASSEMBLER: ;Place your asm routines here
; db ........
; db ........
; db ........
;----------------------------------
;BASIC program
;----------------------------------
BASIC_PROG: ;Place the compressed BASIC prog. here
; db ........
; db ........
; db ........
;----------------------------------
;CHARACTER SET
;----------------------------------
CHAR_SET: ;Place the character set here
; db ........
; db ........
; db ........
ENDCODE: ;This will generate a .txt file with
;info about size and free memory
.printtext "Size :"
.print (ENDCODE-BEGIN)
.printtext "Free space :"
.print (4000h-(ENDCODE-BEGIN))
I hope you find it useful