Welcome to Schneider / Amstrad CPC Forum. Please login or sign up.

20. April 2024, 04:54:58

Login with username, password and session length

Shoutbox

TFM

2024-04-08, 20:42:44
Happy Sonnenfinsternis!  :)

TFM

2024-01-15, 17:06:57
Momentan billige Farbbänder auf Ebay für PCW

Devilmarkus

2023-07-09, 10:37:40
Zweiter 👋😂🤣

TFM

2023-06-13, 14:21:49
Sommerloch!

TFM

2023-05-30, 17:00:20
Erster ;-)

Recent

Members
Stats
  • Total Posts: 11,695
  • Total Topics: 1,336
  • Online today: 185
  • Online ever: 1,724
  • (16. January 2020, 00:18:45)
Users Online
Users: 0
Guests: 150
Total: 150

150 Guests, 0 Users

Den eingeblendeten Block sichtbar machen von einer Bank.

Started by cpcman, 17. November 2018, 18:00:50

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

cpcman

Hallo, guten Tag.

Ich habe in einer Bank 4 Blöcke reingelegt die eine Grafik enthalten.
Nun blende ich die Blöcke der Bank in $4000 ein kopiere nach $c000.
Das klappt.

Nun möchte ich aber den Block in $4000 nicht kopieren nach $c000 sondern möchte den
Screen dort drauf schalten damit ich diesen Bereich von $4000  sehe.
--------------------------
ld a,#40
call #bc08   
--------------------------

Das bekomme ich nicht hin.
Gibt es dafür ein Trick?

Danke.
Gruss

Devilmarkus

#1
Wieso verwendest du nicht das CRTC Register dafür?

LD BC,&BC0C
OUT (C),C
LD BC,&BD10
OUT (C),C

Zurück:

LD BC,&BC0C
OUT (C),C
LD BC,&BD30
OUT (C),C
https://cpcwiki.de
Dein Deutsches CPCWiki!

cpcman

Danke.

Funktioniert nicht.
Habe den cpc6128 Modus, liegt es daran? Schaltet nicht um.

Gruss

TFM

Der CPC kann nur die ersten 64 KB als Bildschirmspeicher verwenden. Also muss man die Grafik in die ersten 64 KB kopieren um sie anzuzeigen.  :)
TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 20.12.2023)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 26.12.2021)

cpcman

Danke das ist mir klar, das 16kb in den bereich von $4000 bis $7fff eingeblendet werden können zur Verwendung.

Ich möchte aber den Bereich von &4000 - &7fff sichtbar machen der von der Bank eingeblendet wird
und nicht nach &c000 copieren. Also den Screen auf $4000 umschalten damit ich die Daten/Bilder sehe.
Auch bekomme ich das Bild bei $c000 nicht zu sehen gemäß Abbildung 4 vom Anhang wenn es dort eingeblendet wird.

Das bekomme ich nicht hin.
Vielleicht klappt es doch mir eurer Hilfe?

Danke.
Gruss

Devilmarkus

Genau das macht mein Code...
Allerdings kannst du, wie TFM schon schrieb, nur den Bereich 4000-7FFF aus Bank &C0 anzeigen lassen...

Solltest du den kompletten Code von mir kopiert haben, geht's natürlich nicht, weil der ja bei "Zurück:" wieder auf C000 schaltet...
https://cpcwiki.de
Dein Deutsches CPCWiki!

cpcman

-------------------------------------
nur den Bereich 4000-7FFF aus Bank &C0 anzeigen lassen...
--------------------------------------

Ja, danke.
Den Code in ASM dafür würde ich mal gerne haben um auf $&4000 den Code von $C000 zu sehen.
Von der Abbildung 4.
Das heisst dann, das ich von jeder Bank die sich auf $c000 schaltet den Code in $4000 sehen kann mit der
entsprechenden Umschalltung des Screens auf $4000.

Danke.
Gruss

Devilmarkus

Wie gesagt, meine Routine ist noch nicht fertig, und enthält auch durchaus noch unsortierten Code...
Allerdings kannst du hier auch gepuffert kopieren...
Such dir raus, was du brauchst...

;
; Basic Sprite Routines Written by Markus Hohmann and Jason Brooks
;

;
; Define Constants
;
TXT_OUTPUT equ #BB5A
KL_LOG_EXT equ #BCD1
SCR_SET_MODE equ #BC0E
SCR_GET_MODE equ #BC11
SCR_SET_BASE equ #BC08
MAX_WIDTH equ 80
MAX_HEIGHT equ 200
;
;
;

;
; Start of Code
;
org #8800
start:
ent $
write direct "a:rsxcode.bin"
LD a,#c9
LD (start),a   ; Stop RSX Being RE-Initialized !
; Intercept Mode Changes
; So we know what mode sprites need to be
; rendered in (future update)
ld a,(SCR_SET_MODE)  ; Firmware call for SCR SET MODE
cp #c3     ; Check we've not patched it before
jr z,skipIntercept  ; If so, Skip it
ld hl,(SCR_SET_MODE+1) ; Intercept mode Changes (Firmware)
ld (intercept+1),hl  ; store the RST Address
;
ld a,#c3    ; Patch #BC0E to point to our routine
ld hl,modeIntercept
ld (SCR_SET_MODE),a
ld (SCR_SET_MODE+1),hl

skipIntercept: ; All done, now get current mode RSX
; Initialised in
call SCR_GET_MODE
ld (currentMode),a  ; Set the current Mode
;

call MemoryCheck  ; Check How much RAM is Installed.

call infoMessage  ; Display Start Up Message
call PreCalculateScreenAddress  ; Set up look up Table

; Initialise the RSX
LD hl,work
LD bc,rsxTable
JP KL_LOG_EXT   ; Call KL LOG EXT

;
; 4 byte work space required by RSX
;
work:
DEFS 4,0    ; RSX 4 Byte Work Table
;
; Current Screen Mode
;
currentMode:
defb 00   ; What is the Current Screen Mode We're in

;
; Patch for the SCR_SET_MODE
;
modeIntercept:
ld (currentMode),a  ; Set the current mode with mode requested
intercept: ; Call the original routine
RST #08
DEFW 00

;
; Start up Message
;

INFO_MESSAGE:
DB &f,3,&18," SCREENRSX 1.0 ",#A4," 2018 by Markus Hohmann ",&18
DB &f,2,&18,"            and Jason Brooks            ",&18,&f,1,&a
DB &f,1,"|BANK,<rambank> ",&f,2,"Set Bank 0-32, max. 576k"
DB &f,1,"|BANK4MB[,<rambank>]  ",&f,2,"Set 4mb Bank 0-256",&a
DB &f,1,"|COPY[,<rambank>]  ",&f,2,"Copy screen [to bank]"
DB &f,1,"|PASTE[,<rambank>]     ",&f,2,"Paste [from bank]",&a
DB &f,1,"|VSYNC       ",&f,2,"wait for next frame flyback"
DB &f,1,"|GETART,x,y,w,h,address,@ln% ",&f,2,"Grab sprite"
DB &f,1,"|PUTART,x,y,address          ",&f,2,"Draw sprite"
DB &f,1,"|PUTARTSYNC,x,y,a ",&f,2,"VSync then draw sprite"
DB &f,3," x=0-79,y=0-199,w=0-79,h=0-199,a=address"
DB &f,3," sprite size is calculated: w*h+2       ",&a
DB &f,1,"|GMODE,<mode>   ",&f,2,"select sprite rendermode"
DB &f,3," 0=XOR, 1=OR, 2=AND, 3=NOP, 4=ADD, 5=SUB",&a
DB &f,1,"|HELP                          ",&f,2,"this info",&f,1,&a,0
INFO_MESSAGE_MEMORY:
DB &f,1,"Additional Memory Installed: ",&f,2
MemoryInstalledString: DEFS 5,#20 ; String for Memory Installed
DB &f,1,"KB",&f,1,#A,#d
DB &f,1,"Use ",&f,2,"|BANK,<0 - "
MaximumBanksString: defs 3,#30
DB ">", &f,1,#a
DB 0

GMODEERROR:
DB "Error"
DB 13,10
DB " |GMODE,(0-4)", #13, #10
DB " 0 = XOR", #13, #10
DB " 1 = OR", #13, #10
DB " 2 = AND", #13, #10
DB " 3 = Overwrite", #13, #10
DB " 4 = ADD", #13, #10
DB " 5 = SUBTRACT", #13, #10
defb 13,10,0

;
; Memory Bank Handling - up to 4MB
;
;
; Bank Table (OUT (C),C) ...
;
4mb_banks:

dw &7FC0, &7FC4, &7FC5, &7FC6, &7FC7, &7FCC, &7FCD, &7FCE, &7FCF, &7FD4
dw &7FD5, &7FD6, &7FD7, &7FDC, &7FDD, &7FDE, &7FDF, &7FE4, &7FE5, &7FE6
dw &7FE7, &7FEC, &7FED, &7FEE, &7FEF, &7FF4, &7FF5, &7FF6, &7FF7, &7FFC
dw &7FFD, &7FFE, &7FFF, &7EC4, &7EC5, &7EC6, &7EC7, &7ECC, &7ECD, &7ECE
dw &7ECF, &7ED4, &7ED5, &7ED6, &7ED7, &7EDC, &7EDD, &7EDE, &7EDF, &7EE4
dw &7EE5, &7EE6, &7EE7, &7EEC, &7EED, &7EEE, &7EEF, &7EF4, &7EF5, &7EF6
dw &7EF7, &7EFC, &7EFD, &7EFE, &7EFF, &7DC4, &7DC5, &7DC6, &7DC7, &7DCC
dw &7DCD, &7DCE, &7DCF, &7DD4, &7DD5, &7DD6, &7DD7, &7DDC, &7DDD, &7DDE
dw &7DDF, &7DE4, &7DE5, &7DE6, &7DE7, &7DEC, &7DED, &7DEE, &7DEF, &7DF4
dw &7DF5, &7DF6, &7DF7, &7DFC, &7DFD, &7DFE, &7DFF, &7CC4, &7CC5, &7CC6
dw &7CC7, &7CCC, &7CCD, &7CCE, &7CCF, &7CD4, &7CD5, &7CD6, &7CD7, &7CDC
dw &7CDD, &7CDE, &7CDF, &7CE4, &7CE5, &7CE6, &7CE7, &7CEC, &7CED, &7CEE
dw &7CEF, &7CF4, &7CF5, &7CF6, &7CF7, &7CFC, &7CFD, &7CFE, &7CFF, &7BC4
dw &7BC5, &7BC6, &7BC7, &7BCC, &7BCD, &7BCE, &7BCF, &7BD4, &7BD5, &7BD6
dw &7BD7, &7BDC, &7BDD, &7BDE, &7BDF, &7BE4, &7BE5, &7BE6, &7BE7, &7BEC
dw &7BED, &7BEE, &7BEF, &7BF4, &7BF5, &7BF6, &7BF7, &7BFC, &7BFD, &7BFE
dw &7BFF, &7AC4, &7AC5, &7AC6, &7AC7, &7ACC, &7ACD, &7ACE, &7ACF, &7AD4
dw &7AD5, &7AD6, &7AD7, &7ADC, &7ADD, &7ADE, &7ADF, &7AE4, &7AE5, &7AE6
dw &7AE7, &7AEC, &7AED, &7AEE, &7AEF, &7AF4, &7AF5, &7AF6, &7AF7, &7AFC
dw &7AFD, &7AFE, &7AFF, &79C4, &79C5, &79C6, &79C7, &79CC, &79CD, &79CE
dw &79CF, &79D4, &79D5, &79D6, &79D7, &79DC, &79DD, &79DE, &79DF, &79E4
dw &79E5, &79E6, &79E7, &79EC, &79ED, &79EE, &79EF, &79F4, &79F5, &79F6
dw &79F7, &79FC, &79FD, &79FE, &79FF, &78C4, &78C5, &78C6, &78C7, &78CC
dw &78CD, &78CE, &78CF, &78D4, &78D5, &78D6, &78D7, &78DC, &78DD, &78DE
dw &78DF, &78E4, &78E5, &78E6, &78E7, &78EC, &78ED, &78EE, &78EF, &78F4
dw &78F5, &78F6, &78F7, &78FC, &78FD, &78FE, &78FF
DW 0 ; Signify End of list DO NOT REMOVE
4mb_size: equ $-4mb_banks

;
; Maximum Memory Size in KB
;
maxMemSizeKB: defw 0


;
; The RSX Table - New Command Jump Table
;
rsxTable:
DEFW rsxCommands  ; Point to Text Command Space
JP InfoMessage  ; Print the startup message
JP Copy
JP Paste
JP Bank
JP Bank
JP getSprite  ; |GETSPR,X,Y,W,H,MEMORYADDRESS
JP putSprite  ; |PUTSPR,X,Y,MEMORYADDRESS
JP putSpriteFFB    ; |PUTSPRFFB,X,Y,MEMORYADDRESS
JP frameFly  ; |FRAMEFLY
JP SetGMode  ; |GMODE,x (0 = XOR, 1 = OR, 2 = AND, 3 = NOP, 4 = ADD, 5 = SUB)
JP doFrame1  ;
JP doFrame2  ;
JP doFrame3  ;
JP doFrame4  ;
JP BackBuff        ; |BACKBUFF,0 = &c000   ,1 = &4000
JP GetMaxBank  ; |GETMAXBANK,@a%
JP GetMaxMem  ; |GETMAXMEM,@a%
JP ScreenCopy  ; |SCRCOPY
JP ScreenPaste  ; |SCRPASTE
JP BankCopy        ; |BANKCOPY,FromBank,ToBank
;
; Text Commands the user calls
;
rsxCommands: ; Added BASIC Commands
DB "HEL","P"+#80  ; |HELP
DB "COP","Y"+#80  ; |COPY,<number>
DB "PAST","E"+#80  ; |PASTE,<number>
DB "BAN","K"+#80  ; |BANK,<number>
DB "BANK4M","B"+&80 ; |BANK4MB,<number>
DB "GETAR","T"+&80  ; |GETSPR,X,Y,W,H,Memory
DB "PUTAR","T"+&80  ; |PUTSPR,X,Y,Memory
DB "PUTARTSYN","C"+&80 ; |PUTSPRFFB,X,Y,Memory  - Await Frame Fly Back
DB "FRAMEFL","Y"+&80 ; |FRAMEFLY
DB "GMOD","E"+#80  ; |GMODE
db "FRAME","1"+#80  ; |FRAME1
db "FRAME","2"+#80  ; |FRAME2
db "FRAME","3"+#80  ; |FRAME3
db "FRAME","4"+#80  ; |FRAME4
DB "BACKBUF","F"+#80   ; |BACKBUFF
DB "GETMAXBAN","K"+#80 ; |GETMAXBANK,@a%
DB "GETMAXME","M"+#80 ; |GETMAXMEM,@a%
DB "SCRCOP","Y"+#80 ; |SCRCOPY,<Bank>  - Copy Screen by Line
DB "SCRPAST","E"+#80   ; |SCRPASTE,<Bank>,Sync - Paste Screen by Line
DB "BANKCOP","Y"+#80   ; |BANKCOPY,<FromBank>,<ToBank>
;
; Required to signify end of Table
;
DEFB 0    ; End of Table


;
; RSX Commands
;

; Markus' Code

infoMessage:
ld a,1
call SCR_SET_MODE
LD A,&dd
LD BC,&EF00
OUT (C),A
LD HL,INFO_MESSAGE     ;ZEIGER AUF PROMT-TEXT
CALL print    ;TEXT AUSGEBEN

ld hl,(maximumBankCount) ; Check Memory Installed
ld a,l
or h      ; Check if HL = 0
ret z      ; Quit Memory Message if Zero
ld hl,INFO_MESSAGE_MEMORY
JP Print

;
; Check how much memory is installed on the CPC
; Note this routine will corrupt memory
;
MemoryCheck:
ld hl,#ffff
ld (maximumBankCount),hl    ; RESET the Memory Bank Counter
ld hl,4mb_banks       ; Point to the 4mb Memory Bank
; Cycle through the port list and set
; #4000 = PORT WORD
MemoryCheckLoop:
call SwitchBank       ; Switch Memory Bank Pointed to in HL
jr z,MemoryCheckNext     ; move to next check if reached the end
ld (#4000),bc       ; Load Memory Address with PORT Pair
jr MemoryCheckLoop      ; Keep Looping until Zero Bytes
;
MemoryCheckNext: ; Check which banks are available
; By reading memory at #4000 and comparing
; it to the PORT Word, ZERO Out any Ports
; Unavailable

ld hl,4mb_banks       ; Point to the 4mb Memory Bank
MemoryCheckLoop2:
call SwitchBank       ; Attempt to Switch Memory In
jr z,MemoryCheckNext2     ; Move to next check if at end of list
push hl         ; Preserve HL Pointer
ld hl,(#4000)       ; load the data from #4000



or a         ; reset carry flag
sbc hl,bc        ; BC will already contain the Port Number
pop hl         ; Restore HL Pointer (memory banks)
call nz,MemoryCheckClearBank ; No match so bank not available
jr MemoryCheckLoop2      ; Keep On Looping
MemoryCheckNext2:
ld HL,4mb_banks       ; Move up all valid entries up the list
push HL
pop DE          ; Save one byte, DE = HL
ld bc,4mb_size/2      ; Number of times to loop
MemoryCheckLoop3:
ld a,(hl)        ; Get first byte and check if it's zero
or a
jr z,MemoryCheckLoop5
push bc         ; Preserve BC
ldi
ldi ; Copy HL to DE, HL = HL + 1, DE = DE + 1
pop bc
push hl         ; preserve HL
ld hl,(maximumBankCount)    ; Bump the counter for the Maximum RAM Banks
inc hl         ; Installed
ld (maximumBankCount),hl    ; And Save it off
pop hl         ; Continue
MemoryCheckLoop4:
dec bc         ; Decrease Counter
ld a,b
or c         ; Have we reached Zero?
jr nz,MemoryCheckLoop3
jr MemoryCheckFinal      ; Final Clear Up
MemoryCheckLoop5: ; Zero Byte Found so move to next register
inc hl
inc hl         ; Point to next WORD
jr MemoryCheckLoop4      ; Count Down...

MemoryCheckFinal:
ld hl,0
maximumBankCount equ $-2     ; Number of Memory Banks Installed (16k each)
ld a,l
or h
ret z         ; Quit if no extra memory found (464)

ld de,MaximumBanksString    ; Convert to Printable number
call ASCIINUMBERH

Ld hl,(maximumBankCount)    ; Get HL
add hl,hl        ; * 2
add hl,hl        ; * 4
add hl,hl        ; * 8
add hl,hl        ; * 16
ld (maxMemSizeKB),hl  ; Store the maximum number in KB
; HL = Number to Print
; DE = Buffer to Stick it
ld DE,MemoryInstalledString ; Point to Ascii Version of memory
ASCIINUMBER:
; ld bc,-10000    ; Work out the 10's Thousands
; call GetDig
ld bc,-1000     ; Work out the Thousands
call GetDig
ASCIINUMBERH: ; Hundreds Only
ld bc,-100     ; Work out the Hundreds
call GetDig
ld bc,-10     ; Work Out the Tens
call GetDig
ld c,-1      ; Work out the units
GetDig
ld a,'0'-1                  ; Set the ASCII #2f since we'll always increment
GetDig1:
inc a                       ; Increment A
add hl,bc                   ; Count the BC units
jr c,GetDig1                ; Continue whilst there's more
sbc hl,bc                   ; a Carry so restore to previous
ld (de),a                   ; set the character in destination string
inc de                      ; increase the pointer to next char string
ret ; quit


;
; Clear the Port from the list that isn't enabled.
; HL must point the entry in the Memory Bank Table
;
MemoryCheckClearBank:
PUSH HL
xor a     ; Reset Accumulator
dec hl     ; HL Will be pointing to next location
ld (hl),a    ; so we need to decrease and Zero Out
dec hl
ld (hl),a    ; Repeat
pop HL     ; Restore HL
ret
;
; Switch Memory Bank pointed to OUT Pair in HL
;
SwitchBank:
ld c,(hl)    ; Load BC with the Correct Port
inc hl     ; For Each Memory Bank
ld b,(hl)
inc hl
ld a,c
or b
jr z,SwitchBankEnd  ; Quit if end of list
out (c),c
SwitchBankEnd:
ret

;
; Return to the user the maximum bank they can select
; |GETMAXBANK,@a%
;
GetMaxBank:
ld hl,maximumBankCount    ; Load HL with Location of maximum Bank Count
GetMaxMem2:
dec a
jr nz,BankOutOfRange    ; Check the user has passed a parameter
ld e,(ix+0)
ld d,(ix+1)       ; Get location of variable.
ldi
ldi ; Copy into variable
ret ; Quit



;
; Return the Maximum Additional Memory Installed in KB
;
GetMaxMem:
ld hl,maxMemSizeKB
jr GetMaxMem2      ; Check and return the variable.
;
; Re-Written Bank Command, Now you can only switch in Valid
; and available banks
;
BankOutOfRange:
ld a,7              ; Bell Character
jp TXT_OUTPUT
Bank:
or a
jr z,BankOutOfRange ; Quit if no parameter supplied (could add error handling)
ld c,(ix+0)
ld b,(ix+1)   ; Get Bank Number Passed in Parameter
BankOffsetCalc:
ld hl,(maximumBankCount) ; Get the Maximum Bank Count
sbc hl,bc
jr c,BankOutOfRange ; Quit if we're requesting an invalid bank
LD HL,4mb_banks  ; Point to Table
add hl,bc
add hl,bc   ; Add 2 * BC to HL to point to correct word
ld C,(HL)
inc HL
ld B,(HL)          ; Get Port Number

ld a,b
or c
ret z    ; Safety Check Quit if Zero Word Selected
out (C),C  ; Switch the bank in
ret

Copy:
or a
jr z,BankOutOfRange ; Quit if no parameter supplied (could add error handling)
call Bank   ; Switch in the Bank
ret c
DoCopy:
XOR A
LD HL,&C000
LD DE,&4000
JR LOOP


Paste:
or a
JR z,BankOutOfRange ; Quit if no parameter supplied (could add error handling)
call Bank   ; Switch in the Bank
ret c
DoPaste:
call frameFly
XOR A
LD HL,&4000
LD DE,&C000
DI
LOOP:
repeat 64
LDI
rend
DEC A
JP NZ,LOOP
EI
ret

; End Markus' Code

;
; SCRCOPY - Copy the Screen line by Line for Re-Rendering
;
ScreenCopy:
or a      ; Has any Parameter Been Passed?
jp z,BankOutOfRange   ; Check we are in Range of Memory Banks Available
call bank     ; Switch in the Selected bank.
ld de,#4000
call PreCalculateScreenAddress; Ensuire not corrupted
DI ; Disable Interrupts

ScreenCopy1:
ld (RestoreSP1),sp   ; Save Stack Pointer
ld sp,scrAddrTable+2  ; Point to the Bottom of the Pre-Calculated Stack
ld a,200     ; 200 Lines of Screen
ScreenCopyLoop:
pop HL
;
; LDI Stack - Quicker at loading memory at fixed 16 T-States per insturction
;
LDI80
repeat 80
LDI
rend

dec a      ; decrease counter
jp nz,ScreenCopyLoop

ld sp,0000     ; Restore Stack Pointer
RestoreSP1 equ $-2
EI ; Enable interrupts again.
ret

;
; Paste the Screen with data from the buffer at #4000
;
ScreenPaste:
or a      ; Has any Parameter Been Passed?
jp z,BankOutOfRange
ld hl,ScreenPasteLoop
cp 1      ; One Paramater Passed?
jr z,ScreenPaste1   ; Increment IX
ld hl,ScreenPasteLoopSync ; Which Routine?
inc ix
inc ix
ScreenPaste1
ld (PasteWithFlyback),hl ; Set Proper Routine
call Bank     ; Set the correct bank to paste from
call PreCalculateScreenAddress ; Gets Corrupts
DI
ld HL,#4000
ld (RestoreSP2),sp   ; Save Stack Pointer
ld sp,scrAddrTable+2  ; Point to the Bottom of the Pre-Calculated Stack
ld a,200     ; 200 Lines of Screen
ScreenPasteLoopSync:
PUSH AF
call frameFly
pop AF

ScreenPasteLoop:
pop DE

;
; LDI Stack - Quicker at loading memory at fixed 16 T-States per insturction
;
LDI80b
repeat 80
LDI
rend
dec a      ; decrease counter
jp nz,ScreenPasteLoop
PasteWithFlyback equ $-2
ld sp,0000     ; Restore Stack Pointer
RestoreSP2 equ $-2
EI ; Enable interrupts again.
ret

;
; Simply Copy Section of Screen into Memory
; |GETSPR, X, Y, W, H, &Address
; Where X = Byte 0-79
; Y = Line 0 -1 199
; W = Width
; H = Height
; Address = Where to Place Sprite
;
getSprite:
cp 6    ; Have we received 5 parameters?
ret nz    ; Quit if we haven't

; Dodgy but Values < 256 so only interested in the LSB
ld h,(ix+10)  ; Get X Coord
ld l,(ix+8)   ; Get Y Coord

; HL  = XY Address

ld b,(ix+6)   ; Get Width
ld c,(ix+4)   ; Get Height

ld d,(ix+3)   ; Get MSB Address
ld e,(ix+2)   ; Get LSB Address

ld a,c    ; Set Height in ROW Count
ld (rowcount),a  ; set the row count of data to get
ld (de),a   ; Store Height Byte At Dest
inc de
ld a,b    ; Get Width
ld (widthCount),a ; Set the width counter
ld (de),a   ; Store Width Byte at Dest + 1
inc de


; So now HL = XY, DE = Width|HEIGHT, BC = Destination

push bc
push de
call calcScrAddr ; Get True Screen Address
pop de
pop bc
push DE    ; Preserve Start Address
call getScreenData;
pop hl    ; DE should contain last byte of storage
ex de,hl   ; Swap
xor a
sbc hl,de
inc hl
inc hl     ; Add two bytes for header
ex de,hl
ld l,(ix+0)
ld h,(ix+1)
ld (hl),e
inc hl
ld (hl),d   ; Store length in Variable
ret

getScreenData:
push hl    ; Preserve Read Address
ld bc,0
widthCount: equ $-2
ldir ; copy row of data

ld a,0
rowcount: equ $-1
dec a
ld (rowcount),a  ; Self Modifying Code
pop hl    ; Restore HL Screen Address
ret z
ld a,8
add a,h
jr nc,getLoop2
ld a,#50
add a,l
ld l,a
ld a,h
adc a,#c8
getLoop2:
or #c0
ld h,a
jr getScreenData


;
; Set Graphics Mode (Basic)
;
SetGMode:
cp 1
ld a,0   ; (Not using XOR A as that resets F)
jr nz,SetGmode1
ld a,(ix+0)  ; Get Value
SetGmode1:
cp 6
jr nc,GMerror
ld hl,GMODESBYTE
ld b,0
ld c,a
add hl,bc
ld a,(hl)
ld (PutMode),a
ret
GMerror:
ld hl,GMODEERROR
print:
ld a,(hl)
or a
ret z
call TXT_OUTPUT
inc hl
jr print
;
; Different Graphics Mode (BASIC)
;
GMODESBYTE:
XOR (hl)
OR (hl)
AND (hl)
NOP
ADD (HL)
SUB (HL)


putSpriteFFB:
push af
call frameFly  ; Display Sprite After FrameFlyBack
pop af
;
; Put SPRITE
;
putSprite:
cp 3    ; Have we received 3 parameters?
ret nz    ; Quit if we haven't

; Dodgy but Values < 256 so only interested in the LSB

; HL  = XY Address

ld h,(ix+4)   ; Get X Position (0-79)
ld l,(ix+2)   ; Get Height (0 - 199)

ld d,(ix+1)   ; Get MSB Address
ld e,(ix+0)   ; Get LSB Address

ld a,(de)   ; Get Height
ld c,a
ld (putRowCount),a ; Self Modifying Code
inc de
ld a,(de)   ; Get Width
ld b,a
ld (putLoop+1),a ; Self Modifying Code
inc de

xor a
ld (putClipOffset),a; Ensure Offset Reset on Every Call

;
; Check to see if Sprite Will Clip on the Boundary
; and adjust accordingly
;
call clippingCheckY;
call c,clippingCheckX;
ret nc              ; No Sprite to display
; push bc
push de
call calcScrAddr
pop de
; pop bc

PutData:
putLoop:
ld b,0
putWidth: equ $-1
push hl
PutLoop1:
ld a,(de)   ; Get Sprite Byte
xor (hl)   ; Xor On Screen
PutMode: equ $-1
ld (hl),a
inc de
inc hl
ld a,h
or #c0
ld h,a    ; Ensure we're on the screen
djnz PutLoop1  ; Loop width
pop HL    ; Restore HL
ld a,0
putRowCount: equ $-1
dec a
ld (putRowCount),a
ret z    ; Quit if we've reached the end
ld a,8
add a,h
jr nc,putLoop2
ld a,#50
add a,l
ld l,a
ld a,h
adc a,#c8
putLoop2:
or #c0
ld h,a
; Offset for clipped sprites
ld a,e
add a,0
putClipOffset: equ $-1  ; Update DE with offset
ld e,a
ld a,d
adc 0
ld d,a
jr putLoop
;
; Check to see if the sprite will clip off screen.
; H = X-Coord, L = Y-Coord, C = Height, B = Width
; DE = Location of Sprite Data
; NC = Failed to Set Sprite Position
; A = Corrupt on Exit
clippingCheckY: ; Initial Check to See if Sprite is Displayable on Y-Axis
LD a,l     ; Get Y-Position
cp MAX_HEIGHT  ; Is it greater than Max Height?
JR NC,clipCheckY3 ; Less than so ok. We know its out of bounds
add a,c    ; Add the height of the sprite
cp MAX_HEIGHT  ; Are we still in bounds?
JR C,clipCheckYOK ; Carry on with next checks
;
; Check to see if Sprite Is Above or Below the Boundary
;

clipCheckY2: ; Sprite is Bottom of Screen and needs clipping

ld a,MAX_HEIGHT  ; Work out how many lines to display
sub L    ; Subtract Height
ld (putRowCount),a  ; Set the Actual Count to use. DE unaltered
jr clipCheckYOK
clipCheckY3: ; Must be nearer the top of screen
ld a,l    ; get height
add c     ; Add Height to see if we can display on screen
ret nc     ; If No Carry, there's nothing to display and quit.
jr z,clipCheckNOK ; Quit as off screen
push bc    ; Preserve Registers (Width & Height)
push hl    ; (X,Y)
push de    ; (DATA)
ld a,l    ; Get Y Position again
neg ; Invert it so we know how many lines to skip
ld d,0
ld e,b     ; LD DE with width
call Multiply  ; Work out offset of Y Data
pop de
add hl,de   ; Add the Offset Together so pointing to correct data
ex hl,de   ; Swap so in correct register
pop hl    ; Restore (X&Y)
pop bc    ; Restore Dimensions

ld a,l    ; Get Y-Coord
add c     ; Add Sprite Height (Should Carry Since L = Negative Value)
ld c,a    ; Set Correct Height
ld (putRowCount),a
ld l,0    ; Reset Y poistion to Top of Screen
; We can display a portion of Sprite.
clipCheckYOK:
SCF ; Set Carry Flag
ret
clipCheckNOK:
xor a    ; Reset Carry Flag
ret

clippingCheckX: ; Check the X-Boundary of the Sprite to Display
ld a,h              ; Get the X-Co-Ordinate
cp MAX_WIDTH        ; Check in Bounds of Width
JR NC,clipCheckX3   ; Outside of Boundary
add a,b             ; Add Width of Sprite
cp MAX_WIDTH        ; Are we still on the screen?
jr c,clipCheckOK    ; All good normal conditions apply

;
; Assuming X + W is outside boundary to the right to calculate offsets
;

ld a,MAX_WIDTH  ; Work out how many bytes to display
sub h    ; Subtract Width
ld (putWidth),a  ; Set the Actual Count to use.
neg ; Invert Width
add a,b             ; Add Width to get Skip Offset
ld (putClipOffset),a; Set the Clipping Byte Offset
jr clipCheckYOK
clipCheckX3: ; Must be to the left of the boundary
ld a,h    ; Get Y-Coord
add b     ; Add Width to see if we can display on screen
ret nc     ; If No Carry, there's nothing to display and quit.
jr z,clipCheckNOK ; Quit as off screen
ld a,h    ; Get X Position again
add a,b             ; Get New Width
ld (putWidth),a     ; Set New Width of Sprite
ld a,h              ; Get X-Position Again
neg ; Invert it so we know how many bytes to skip
ld (putClipOffset),a; Set the number of bytes to skip
add a,e             ; Add bytes to Ignore to DE
ld e,a
ld a,d
adc 0               ; Update DE for Start Offset
ld h,0              ; Set X to Left Hand Boundary
clipCheckOK:
SCF ; Set Carry Flag
ret

;
; Routine to calculate Screen Address from H = X, L = Y
; Optimised - Jason Brooks
calcScrAddr: ; Entry L=Row (0-199) , E=Column (0-79)
LD e,h
LD h,0
LD a,l
AND 7    ; MOD to work out which row in screen memory to point to
ADD a,a
ADD a,a
ADD a,a   ; multiply by 8 (i.e. row * #800)
LD c,a   ; Store result in C for now...
SRL l    ; Divide Row by 8 to get the #50 offset
SRL l
SRL l
LD a,l   ; Get Row / 8 and Multiply by #50
ADD a,a   ; * 2
ADD a,a   ; * 4
ADD a,l   ; * 5
ADD a,a   ; * 10
LD l,a
ADD hl,hl
ADD hl,hl
ADD hl,hl   ; * 80
LD a,c   ; Finally add the sub row to h
ADD a,h
OR #c0   ; Ensure a valid screen address
LD h,a
LD a,e
ADD a,l
LD l,a
ADC a,h
SUB l
OR #c0   ; ensure a valid screen address
LD h,a
RET

;
; Await Frame Fly Back
;
framefly: ; Hardware Control Routines
LD b,#f5
frameFlyLoop:
IN a,(c)
RRA
RET c
JR frameFlyLoop

;
; Multiply DE * A, Result in HL, No Regs Preserved
;
multiply:
LD hl,0    ; Reset Result
ld b,8    ; Set number of Bits to Check in A
mulLoop:
ADD HL,HL   ; Multiply HL * 2
RLCA ; Shift the A register to the left, left most bit into Carry
JR NC,mulSkip  ; Skip if not multiplying
add hl,de   ; Odd Bit so add orginal
mulskip:
djnz mulLoop  ; Repeat for 8 bits
ret

doframe1:
ld hl,&4000
jr doframe
doframe2:
ld hl,&4028
jr doframe
doframe3:
ld hl,&63c0
jr doframe
doframe4:
ld hl,&63e8
doframe:
LD A,100
LD DE,&D000+20+480 ;; position in screen: this is exact the center
frameLoop:
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi
;
; BC26 for the &C000
;
;
EX DE,HL
LD BC,&800-40
add hl,bc
JR NC,jump
;
ld bc,&c000+80
add hl,bc
;
jump:
EX DE,HL
;
;
; DE = new offset on the screen
;
; *******************************************************
;
;
; now we refresh the address of the graphical source...
;
LD BC,&800-40
add hl,bc


; JR NC,jump2
;
; ld bc,&4000+80
; add hl,bc
;
bit 7,h ; test if we have reached &8xxx page
;
jr z,jump2
;
res 7,h ; loop to &4000
ld bc,&4000+80
add hl,bc
;
jump2
DEC A
JP NZ,frameLoop
ret
;
; BackBuffer On/Off
;
BackBuff:
LD E,#c0    ; Screen Address to #c0
LD BC,#BC0C    ; Register 12
out (c),c    ; Prime Register 12
LD C,#30    ; Assume #c000
or a     ; Check if Parameter has been passed if not
jr z,backBuffOff  ; protect code and default to normal screen
or a,(ix+0)    ; Get parameter passed
jr z,backBuffOff
ld C,#18    ; set for #4000
LD E,#40

backBuffOff:
DI ; Need Exclusive use of the CRTC Registers
call frameFly
LD B,#BD    ; Restore B from Framefly Command - C already set
out (c),c
LD BC,#BC0D    ; Set Register 13 position to 0
out (c),c
ld BC,#BD00
out (c),c
EI ; Enable interrupts
ld a,e
JP SCR_SET_BASE      ; Set the Screen Base




;
; Disposable Code - Code Beyond This Point for One-Time Use Only at Initialisation
; It will be re-used as various work buffers for sprites etc.
;
DisposableCodeSegment:

;
; Pre-Calculate Left Handed Screen Addresses Row By Row
; To Save Memory, you can just take the completed Table
;
;PreCalculateScreenAddress:
; DI      ; Disable Interrupts
; ld b,200                ; Two Hundred Lines
; ld hl,#C000             ; Top Left Screen Address
; ld (restoreSP), SP      ; Save the Stack Pointer
; LD SP,scrAddrTableEnd   ; Point to Top of Pre-Calculated Space
;PCSAL1:
; PUSH HL                 ; Store Address on Stack
; ld a,8                  ; Update HL with next line of Screen Address
; add a,h                 ; Add #800 to HL
; jr nc,PCSAL2            ; If C need to add #c050
; ld a,#50                ; Next Line
; add a,l                 ; Add to L = xx50
; ld l,a                  ; Set L
; ld a,h                  ; Get H
; adc a,#c8               ; Add with Carry to get next screen address
;PCSAL2:
; or #c0                  ; Ensure valid Address
; ld h,a                  ; Set H
; djnz PCSAL1             ; Loop Until Done
; ld sp,#0                ; Reset the SP
;restoreSP: equ $-2
; EI      ; ReEnable Interrupts
; ret                     ; Quit


PreCalculateScreenAddress:
DI ; Disable Interrupts
ld b,200                ; Two Hundred Lines
ld hl,#FF80             ; Top Left Screen Address
ld (restoreSP3), SP      ; Save the Stack Pointer
LD SP,scrAddrTableEnd   ; Point to Top of Pre-Calculated Space
PCSALD1:
PUSH HL                 ; Store Address on Stack
ld a,h                  ; Update HL with next line of Screen Address
sub 8                 ; Add #800 to HL
CP #c0
jr nc,PCSALD2            ; If C need to add #c050
ld a,l
sub #50                 ; Add to L = xx50
ld l,a                  ; Set L
ld a,h                  ; Get H
ccf
adc a,#37               ; Add with Carry to get next screen address
PCSALD2:
or #c0                  ; Ensure valid Address
ld h,a                  ; Set H
djnz PCSALD1             ; Loop Until Done
ld sp,#0                ; Reset the SP
restoreSP3: equ $-2
EI ; ReEnable Interrupts
ret ; Quit

;
; Bank Copy - Routine to COPY memory from one Memory Bank to another Memory Bank
; all in the #4000 range.
;
BankCopy:
cp 2
jp nz,BankOutOfRange                ; Check we have two Parameters Passed
ld c,(ix+0)
ld b,(ix+1)                   ; Get From Bank Number Passed in Parameter
call BankOffsetCalc
ret c                               ; Quit if an issue
ld (switchBank2+1),bc                 ; Store Switch Port
ld c,(ix+2)
ld b,(ix+3)                   ; Get From Bank Number Passed in Parameter
call BankOffsetCalc                 ; BC = PORT (Destination)
ret c
ld (switchBank1+1),bc
DI

LD HL,#4000                         ; Start Address
ld (SwitchBank1Source),hl           ; Set Start Address
ld (switchBank2Destination),hl      ; Set Destination
ld a,8                              ; Number of Loops
ld (SwitchBankCount),a              ; Set number of loops



;
; First Switch From Bank In
;
switchBank1:
LD BC,0
out (C),c
ld hl,#4000                         ; Start to Read Memory From
SwitchBank1Source: equ $-2              ; Update Address
ld DE,buffer                        ; Put Data in the Buffer
ld bc,2048                          ; Size of Buffer
SwitchBank1Loop:
Repeat 128                          ; 128 LDI's
LDI
rend
ld a,b
or c                                ; Have we reached the end?
jp nz,SwitchBank1Loop
ld (SwitchBank1Source),HL           ; Preserve Pointer
; Switch Buffer and Copy Back to from Buffer

switchBank2:
LD BC,0
out (c),c
ld de,#4000                         ; Destination
switchBank2Destination: equ $-2
ld hl,buffer                        ; point to buffer
ld bc,2048
SwitchBank2Loop:
Repeat 128                          ; 128 LDI's
LDI
rend
ld (switchBank2Destination),de      ; preserve destination
ld a,b
or c                                ; Have we reached the end?
jp nz,SwitchBank2Loop
ld a,0
SwitchBankCount: equ $-1
dec a
ld (SwitchBankCount),a
jp nz,switchBank1
EI
ret

;
;
;
defs 10,0
scrAddrTable: defs 402,#c0 ; Allow for one PUSH on call Stack...
scrAddrTableEnd:

buffer: defs 2048,0   ; Buffer for Bank Copy
https://cpcwiki.de
Dein Deutsches CPCWiki!

cpcman

Danke für die Info.

Das beantwortet nicht meine Frage von oben.
Bank/Block auf $4000/$c000 schalten wie  es in der PDF Abbildung 4. ist
und $4000 sichtbar machen mit den Umschaltbefehl ohne die Daten umzuschaufeln.

Du kopierst auch nur von $4000 nach $c000 und zurück.

Wahrscheinlich funktioniert meine Frage oben nicht und man muss immer kopieren.

Gruss

Devilmarkus

LD BC,&BC0C
OUT (C),C
LD BC,&BD10
OUT (C),C

Macht den Speicherbereich 4000-7FFF sichtbar, wo ist das Problem?
https://cpcwiki.de
Dein Deutsches CPCWiki!

cpcman

Das  ist nicht das Problem. Ich habe ein anderes.
Vielleicht habe ich es oben nicht ganz klar beschrieben.

-----------------------
Bank/Block auf $4000/$c000 schalten wie  es in der PDF Abbildung 4. ist
-----------------------

Teste es doch mal  bitte:
- Müll den Bereich &4000 mal mit Daten zu.
- dann speicherst du die Daten von &4000 in eine Bank und  in den 3. Block.
- Speicherbereich &4000 löschen
- Bank gem. Abbildung 4. der PDF reinholen (ist Bereich &c000 und der Bereich &4000)
- dann schalte den Screen sichtbar auf &4000
- dann schaue ob du deine Daten die du vorher in die Bank gebracht hast siehst.

Würde mich auf den funktionierenden ASM-Code freuen, weil ich es nicht hin bekomme.

Gruss

Devilmarkus

Ich wage jetzt mal die These aufzustellen, dass es nicht möglich ist, eine andere Ram-Bank, als C0, an &C000 zu legen.
Bzw, falls dem so ist, würdest du dann ja C000 überschreiben und nicht 4000
https://cpcwiki.de
Dein Deutsches CPCWiki!

cpcman

Gemäß Abbildung 4. werden die Daten in &c000 und &4000 gleichzeitig reingepackt.
Darum wollte ich dann auf &4000 umschalten den Screen.

Weil es nicht funktioniert bei mir  nehme ich auch an, das da der Wurm drin ist.
Da ich Anfänger bin , dachte ich der Fehler liegt bei mir.

------------------------------------
würdest du dann ja C000 überschreiben und nicht 4000
-----------------------------------
&c000 und &4000 werden da zusammen beschrieben. Darum wollte ich auf Screen &4000 schalten.


Gruss

Devilmarkus

Ja hab ich schon 2x gelesen...
Ich kenne mich damit aber genauso wenig aus...
https://cpcwiki.de
Dein Deutsches CPCWiki!

cpcman

Also müssen wir uns doch mit den Umkopieren plagen.

Gruss