; There is some important CrASH programming information in here, so Bill ; Nagel let me release the source to this editor. ; ; This document contains information on how to use the VAT within CrASH. I ; never bothered to document vat_read very well, since it comes directly from ; the source to CrASH 2.0. ; ; Because of relocation, there is a requirement that should sound familiar if ; you have programmed AShell 83 before - ALL VARS YOU ACCESS MUST BE UPLOADED ; *AFTER* YOUR PROGRAM. I can't stress this enough... ; ; To make things easier, the routine vat_read is included somewhere in this ; long program. vat_read is a general purpose VAT scanning routine. You ; feed it the address of a routine to call in HL, and it will begin scanning ; the VAT. ; ; It will go through every entry in the VAT until you do a double return ; (how to do this is located at instructional_label) or until the VAT runs ; out. For each entry, it will put the contents of the current entry ; UNREVERSED into OP1 and OP2 (assume OP2 will be destroyed even though in ; some cases it won't be). It then calls the routine you fed it in HL. ; ; When your routine is called, BC contains the address of the VAT entry, and ; OP1-OP2 contains the current VAT entry. BC won't be useful to most people. ; ; The format of the VAT entry is the same as the 83 (except for list names), ; unreversed. For programs, it's this: ; ; 05 address(2 bytes) size_of_name name ; 05 can be 06 (06 = edit locked program) ; ; For CrASH, it would be (address of CrASH is always 8D24): ; 06 24 8D 05 C R A S H ; ; You can feed OP1+3 directly to D_LT_STR or D_LM_STR since it's a length- ; indexed string. ; ; I hope this is enough. ; ; -- Barubary (darkstar_usa@pipeline.com) - porter of the level editor #include "crash82.inc" #DEFINE mem TEXT_MEM2 #DEFINE gbuf GRAPH_MEM #DEFINE map APD_BUF #DEFINE emap TEXT_MEM #define VAT_END_ADDR $8D12 #DEFINE cx mem #DEFINE cy mem+1 #DEFINE bx mem+2 #DEFINE by mem+3 #DEFINE block mem+4 #DEFINE level1 mem+5 #DEFINE level mem+7 #DEFINE found_zpwld mem+8 #DEFINE timer mem+100 #DEFINE width 66 .db "Penguins Level Editor v1.1",0 call _clrlcdfull call _homeUp call drawblock_xor_clear ld a,(INT_STATE) or a jr z,nointerrupt ld hl,interruptstring ROM_CALL(D_ZT_STR) jp CR_KHAND nointerrupt: ld hl,str_title call _puts call _newline ld hl,str_author call _puts ; Get name of program into OP1 call getprogname call _chkfindsym ; look up ret c inc de inc de ld (level1),de ld a,0 ld (timer),a ld (level),a inc a ld (block),a ld a,5 ld (bx),a xor a ld (by),a call loadlevel main: halt call _getk call _op2toop1 call _convop1 ld a,e cp 24 jp Z,left cp 26 jp Z,right cp 25 jp Z,up cp 34 jp Z,down cp 21 jp Z,change cp 95 jp Z,nextblock cp 85 jp Z,prevblock cp 92 jp Z,levelone cp 93 jp Z,leveltwo cp 94 jp Z,levelthree cp 82 jp Z,levelfour cp 83 jp Z,levelfive cp 11 jr Z,addenemy cp 45 jp Z,savelevel push af ld hl,timer ld a,(hl) inc a ld (hl),a cp $18 jr nz,main_done xor a ld (hl),a call drawblock_xor_swap call drawcursor call CR_GRBCopy main_done: pop af cp 15 jr NZ,main jp savelevel incc: inc c ret addenemy: call _GRBUFCLR call _clrlcdfull set 7,(iy+$14) ld hl,$0f14 ld (GRAF_CURS),hl ld hl,enemystring ROM_CALL(D_ZM_STR) ld h,1 call putenemy aloop: push hl halt call _getk call _op2toop1 call _convop1 pop hl ld a,e cp 24 jr Z,eleft cp 25 jr Z,eleft cp 26 jr Z,eright cp 34 jr Z,eright cp 105 jr NZ,aloop ld d,0 ld a,(bx) ld e,a ld a,(by) sla a sla a sla a sla a ld b,a ld a,h and %00001111 or b ld hl,emap add hl,de ld (hl),a call draw_screen jp main eright: inc h ld a,h cp 10 call Z,righttoo call putenemy jr aloop righttoo: ld h,0 ret eleft: dec h ld a,h cp 255 call Z,lefttoo call putenemy jr aloop lefttoo: ld h,9 ret putenemy: push hl ld a,h ld hl,gfx_enemy sla a sla a sla a ld d,0 ld e,a add hl,de ex de,hl ld b,5 ld c,3 call drawblock call GRBUFCPY_V pop hl ret levelone: call savelevel ld a,0 ld (level),a call loadlevel jp main leveltwo: call savelevel ld a,1 ld (level),a call loadlevel jp main levelthree: call savelevel ld a,2 ld (level),a call loadlevel jp main levelfour: call savelevel ld a,3 ld (level),a call loadlevel jp main levelfive: call savelevel ld a,4 ld (level),a call loadlevel jp main nextblock: call clear_cursor ld a,(block) inc a cp 16 call Z,tooright ld (block),a call draw_screen jp main tooright: ld a,0 ret prevblock: call clear_cursor ld a,(block) dec a cp 255 call Z,tooleft ld (block),a call draw_screen jp main tooleft: ld a,15 ret change: ld a,(by) ld h,width ld l,a call _htimesl ld a,(bx) ld d,0 ld e,a add hl,de ld de,map add hl,de ld a,(block) ld (hl),a jp main clear_cursor: call drawblock_xor_clear ld hl,timer ld (hl),0 ret left: call clear_cursor ld hl,bx ld a,(hl) or a jp z,main dec (hl) call draw_screen jp main right: call clear_cursor ld hl,bx ld a,(hl) cp width-1 jp z,main inc (hl) call draw_screen jp main up: call clear_cursor ld hl,by ld a,(hl) or a jp z,main dec (hl) call draw_screen jp main down: call clear_cursor ld hl,by ld a,(hl) cp 7 jp z,main inc (hl) call draw_screen jp main draw_screen: ld a,0 ld (cy),a yloop: ld a,0 ld (cx),a ld a,(cy) ld h,width ld l,a call _htimesl ld de,map add hl,de ld a,(bx) sub 5 cp 0 call M,offscreen ld e,a ld d,0 add hl,de xloop: ld a,(hl) push hl ld h,8 ld l,a call _htimesl ld de,gfx_space add hl,de ex de,hl ld hl,cx ld a,(bx) add a,(hl) cp 71 call P,roscreen ld a,(cx) ld b,a ld a,(cy) ld c,a call drawblock pop hl inc hl ld a,(cx) inc a ld (cx),a cp 12 jr nz,xloop ld a,(cy) inc a ld (cy),a cp 8 jr nz,yloop call drawcursor ld a,(bx) ld d,0 ld e,a ld hl,emap add hl,de ld a,(hl) and %00001111 ld hl,gfx_enemy sla a sla a sla a ld d,0 ld e,a add hl,de ex de,hl ld b,11 ld c,0 call drawblock call GRBUFCPY_V ret drawcursor: ld hl,gfx_space ld a,(block) sla a sla a sla a ld d,0 ld e,a add hl,de ex de,hl ld b,5 ld a,(bx) cp 5 call M,curleft ld a,(by) ld c,a jp drawblock_xor roscreen: ld de,gfx_block ret curleft: ld b,a offscreen: ld a,0 ret drawblock_xor_clear: xor a ld (drawblock_xor+1),a ret drawblock_xor_swap: ld hl,drawblock_xor+1 ld a,(hl) xor $FF ld (hl),a ret drawblock_xor: ld a,$FF jr drawblock_cont drawblock: ld a,$00 drawblock_cont: ld (picdraw_modify+1),a push de push bc ld h,96 ld l,c call _htimesl pop bc ld c,b ld b,0 add hl,bc ld bc,gbuf add hl,bc pop de ld b,8 picdraw: ld a,(de) picdraw_modify: or $00 ld (hl),a push de ld de,12 add hl,de pop de inc de djnz picdraw ret loadlevel: ld a,(level) ld l,a ld h,165 call _htimesl add hl,hl ld de,(level1) add hl,de push hl ld de,264 add hl,de ld de,emap ld bc,width ldir pop hl ld bc,264 ld de,map convert: ld a,(hl) push af srl a srl a srl a srl a ld (de),a inc de pop af and 15 ld (de),a inc de inc hl dec bc ld a,b or c jr NZ,convert call draw_screen ret savelevel: ld a,(level) ld l,a ld h,165 call _htimesl add hl,hl ld de,(level1) add hl,de push hl ld de,264 add hl,de ex de,hl ld hl,emap ld bc,width ldir pop hl ld bc,264 ld de,map convert2: push bc ld a,(de) sla a sla a sla a sla a and %11110000 ld b,a inc de ld a,(de) and %00001111 or b ld (hl),a pop bc inc de inc hl dec bc ld a,b or c jr NZ,convert2 ret _clrlcdfull: ROM_CALL(CLEARLCD) ret _homeUp: ROM_CALL($391A-$1A) ret _puts: ROM_CALL(D_ZT_STR) ret _newline: ROM_CALL(NEXT_LINE) ret _getk: ROM_CALL($2F48-$1A) ret _convop1: ROM_CALL($35BA-$1A) ret _zeroop1: ROM_CALL($1B21-$1A) ret _chkfindsym: _findsym: ROM_CALL($213E-$1A) ret _op2toop1: ROM_CALL($1A0F-$1A) ret _GRBUFCLR: push hl push de push bc ld hl,GRAPH_MEM ld de,GRAPH_MEM+1 ld bc,767 ld (hl),0 ldir pop bc pop de pop hl ret _htimesl: ROM_CALL($1F18-$1A) ret ; NO _ FOR A REASON - crash82.inc has _GRBUFCPY_V defined GRBUFCPY_V: jp CR_GRBCopy ; Put program to edit into OP1 getprogname: ; HALT is used - avoid screwups ei ld hl,$0104 ld (CURSOR_POS),hl ld hl,getprogstring call _puts ld hl,found_zpwld ld (hl),$00 getprogname2: ld hl,getprogname_handler call vat_read ; Don't get caught in an infinite loop if none found ld a,(found_zpwld) or a jr nz,getprogname2 pop hl call _clrlcdfull call _homeUp ld hl,nolevels call _puts push hl call _newline call _newline pop hl call _puts jp CR_KHAND getprogname_handler: ld a,(OP1) ; Check to see if it's a program or protected program ; If it's not, we don't care -> return. cp $05 jr z,getprog_continue cp $06 ret nz getprog_continue: ; Check for name length > 5 ld a,(OP1+3) cp $06 ret c ; Check for ZPWLD ld hl,OP1+4 ld de,zpwld ld b,5 getprog_checkname: ld a,(de) cp (hl) inc hl inc de ret nz djnz getprog_checkname ; Make sure it's 1650 bytes long ld hl,(OP1+1) call LD_HL_MHL ld de,1650 call CP_HL_DE ret nz ; Mark that one was found ld (found_zpwld),a ld hl,$0105 ld (CURSOR_POS),hl ld hl,OP1+3 ; Length indexed -> D_LT_STR ROM_CALL(D_LT_STR) ld b,8 getprog_clear: ld a,$20 push bc ROM_CALL(TX_CHARPUT) pop bc djnz getprog_clear getprog_getkey: halt call GET_KEY cp G_ALPHA ret z cp G_2ND jr z,instructional_label cp G_ENTER jr nz,getprog_getkey instructional_label: ; Without this, 2nd would edit the level when pressed to load level set ld a,G_ENTER call STORE_KEY ; When "ret" occurs, return to main pop hl pop hl pop hl ld hl,(OP1+1) ld de,end_of_editor call CP_HL_DE jr c,overlap ; Copy name into OP3 then OP1 ; _ZEROOP3 ROM_CALL($1B2B-$1A) ; Get length ld hl,OP1+3 ld b,0 ld c,(hl) inc hl ld de,OP3+1 ldir ld a,$05 ld (OP3),a ; _OP3TOOP1 ROM_CALL($19DA-$1A) ret overlap: ROM_CALL(CLEARTEXT_F) call _homeUp ld hl,overlap_string ROM_CALL(D_ZT_STR) ld hl,CURSOR_ROW inc (hl) ld hl,overlap_string2 ROM_CALL(D_ZT_STR) pop hl jp CR_KHAND ; 83 version must be different (variable-sized-name lists) vat_read: ld (vat_read_call+1),hl ld hl,$FE6E vat_read_loop: ld a,(hl) and $1F cp $05 jr z,vat_read_program cp $06 jr z,vat_read_program ld b,$06 jr vat_read_cont vat_read_program: push hl dec hl dec hl dec hl ld a,(hl) add a,4 ld b,a pop hl vat_read_cont: ld de,OP1 push hl ; Save address of VAT entry for user routine call inv_copy pop bc xor a ld (OP1+12),a ; Force a terminating 0 on 8-letter prog name push hl vat_read_call: call $0000 ; Call program-defined routine pop hl ld de,(VAT_END_ADDR) ; Check for end of VAT call CP_HL_DE ret c ret z jr vat_read_loop inv_copy: ld a,(hl) dec hl ld (de),a inc de djnz inv_copy ret gfx_enemy: .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00111100 .db %01111110 .db %11011011 .db %11111111 .db %11100111 .db %01111110 .db %01111100 .db %00000110 .db %00000000 .db %00000000 .db %01000010 .db %00111100 .db %01000010 .db %00111100 .db %01000010 .db %00111100 .db %00000000 .db %00011110 .db %11111100 .db %11111000 .db %01110000 .db %00110000 .db %00011000 .db %00000000 .db %00000000 .db %00111100 .db %01010110 .db %11111111 .db %11111111 .db %11111111 .db %01111110 .db %00111100 .db %00100100 .db %00011000 .db %01111110 .db %10111101 .db %00111100 .db %01011010 .db %00100100 .db %00000000 .db %00111100 .db %01111110 .db %11011011 .db %11111111 .db %10111101 .db %11000011 .db %01111110 .db %00111100 .db %01011010 ;15 .db %10100101 .db %11100111 .db %11111111 .db %01111110 .db %00011000 .db %00000000 .db %00000000 .db %00001111 .db %00011111 .db %01101111 .db %11111111 .db %11111111 .db %01111111 .db %00011111 .db %00000000 .db %00011000 .db %00111110 .db %00101111 .db %00000101 .db %10000111 .db %11001111 .db %11111111 .db %01111110 gfx_space: .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 gfx_block: .db %00000001 .db %01010101 .db %00101011 .db %01010101 .db %00101011 .db %01010101 .db %00101011 .db %11111111 .db %01111111 .db %10000100 .db %10100001 .db %10001010 .db %11010101 .db %10101010 .db %11010101 .db %10101010 .db %11111111 .db %00000100 .db %00100001 .db %10001010 .db %01010101 .db %10101010 .db %01010101 .db %10101010 .db %11111110 .db %00000101 .db %00100001 .db %10001011 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %11010101 .db %10101010 .db %11010101 .db %10101010 .db %11010101 .db %10101010 .db %11010101 .db %10101010 .db %01010101 .db %10101010 .db %01010101 .db %10101010 .db %01010101 .db %10101010 .db %01010101 .db %10101010 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %01111110 ;8 .db %11000011 .db %10100111 .db %10011111 .db %10011111 .db %10111111 .db %11111111 .db %01111110 .db %11111111 .db %10000001 .db %10110001 .db %10100001 .db %10000001 .db %10000001 .db %10000001 .db %11111111 .db %00010000 .db %01010100 .db %00111000 .db %11111110 .db %00111000 .db %01010100 .db %00010000 .db %00000000 .db %00000000 .db %10000010 .db %10000010 .db %01010100 .db %01010100 .db %00101000 .db %00101000 .db %00000000 .db %00000000 ;12 .db %00000000 .db %00000000 .db %00000000 .db %11111111 .db %11011010 .db %10100101 .db %00000000 .db %00110110 .db %01001001 .db %10000000 .db %10100000 .db %01000000 .db %10000010 .db %10010001 .db %01101110 .db %11101110 .db %00010001 .db %10000001 .db %00000110 .db %00000001 .db %00100001 .db %00010010 .db %11101100 .db %11111111 .db %11111111 .db %11111111 .db %11111111 .db %11111111 .db %11111111 .db %11111111 .db %11111111 str_title: .db " Penguins Level " .db " Editor v1.1",0 str_author: .db " By Bill Nagel",0 getprogstring: .db "Select levels:",0 nolevels: .db "ERROR:",0 .db "No level data " .db "found.",0 interruptstring: .db "ERROR: Interrupt" .db "handler in use. " .db "Disable before " .db "running Level " .db "Editor.",0 overlap_string: .db "OVERLAP ERROR ",0 overlap_string2: .db "You must upload " .db "your level AFTER" .db $DC,"Editor.",0 zpwld: .db "ZPWLD" enemystring: .db "Select Enemy:",0 end_of_editor: